/*
Copyright (C) 2000-2010  Ministere de la culture et de la communication (France), AJLSM
See LICENCE file
 */
package fr.gouv.culture.sdx.utils.zip;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;

import fr.gouv.culture.sdx.exception.SDXException;
import fr.gouv.culture.sdx.utils.Utilities;

/**
 * @author jlecren
 *
 * Have some useful feature about zip files
 */
public class ZipWrapper {
	
	/**
	 * Zip dir2zip in output_file_path
	 * @param output_file_path
	 * @param dir2zip
	 * @throws SDXException
	 */
	public void zipDirectory(String output_file_path, String dir2zip) throws SDXException
	{
		FileOutputStream fo = null;
		ZipOutputStream zos = null;
		try{
			fo = new FileOutputStream(output_file_path);
			zos =new ZipOutputStream(fo);
			zipDirectory(zos,dir2zip,null);
		}catch(IOException e)
		{
			throw new SDXException(e.getMessage(),e);
		}finally
		{
			try{
				if(zos != null)
					zos.close();
				if(fo != null)
					fo.close();
			}catch(IOException e)
			{
				throw new SDXException(e.getMessage(),e);
			}
		}
	}
	
	public void unzipDirectory(String input_file_path, String unzip_dir) throws SDXException
	{
		try{
			ZipFile zfile = new ZipFile(input_file_path);
			byte[] b = new byte[512];
			int len = 0;
			
			for(Enumeration _enum=zfile.entries(); _enum.hasMoreElements();)
			{
				ZipEntry ze = (ZipEntry)_enum.nextElement();
				if(ze.getName().endsWith("/"))
					new File(unzip_dir + ze.getName()).mkdir();
				else
				{
					File file = new File(unzip_dir + File.separator + ze.getName());
					FileOutputStream fo = new FileOutputStream(file);
					InputStream in = zfile.getInputStream(ze);
					while((len = in.read(b))>0)
						fo.write(b, 0, len);
					in.close();
					fo.close();
					file.setLastModified(ze.getTime());
				}
			}
			
		}catch(IOException e)
		{
			throw new SDXException(e.getMessage(),e);
		}
	}
	
	/**
	 * Zip a directory in the file system 
	 * @param output
	 * @param base_dir
	 * @param relative_path
	 * @param file_name
	 * @throws SDXException
	 */
	public void zipDirectory(ZipOutputStream output, String base_dir,  String relative_path) throws SDXException
	{
		String dir_name = "";
		if(relative_path != null)
			dir_name = File.separator + relative_path;
		else
			relative_path = new String("");
		
		File dir = new File(base_dir + dir_name);
		File[] files_name = dir.listFiles();
		for(int i=0; i<files_name.length; i++)
		{
			File f = files_name[i];
			if(f.isDirectory())
			{
				String entry_name = relative_path + File.separator + f.getName();
				entry_name = Utilities.replaceAllSubString(entry_name, File.separator,"/");
				if(!entry_name.endsWith("/"))
					entry_name = entry_name + "/";
				ZipEntry e = new ZipEntry(entry_name);
				try{
					output.putNextEntry(e);
				}catch(IOException ee)
				{
					throw new SDXException("Error while creating a directory entry in the zip file.",ee);
				}
				zipDirectory(output, base_dir, relative_path + File.separator + f.getName());
			}
			else
				zipFile(output, base_dir, relative_path, f.getName());
				
		}
	}
	
	/**
	 * Zip a file in the file system 
	 * @param output
	 * @param base_dir
	 * @param relative_path
	 * @param file_name
	 * @throws SDXException
	 */
	static public void zipFile(ZipOutputStream output, String base_dir, String relative_path, String file_name) throws SDXException
	{
		byte b[] = new byte[512];
		InputStream in = null;
		File file = null;
		try{
			file = new File(base_dir + File.separator + relative_path + File.separator + file_name);
			in = new FileInputStream(file);
		}catch(FileNotFoundException ee){
			throw new SDXException(ee.getMessage(),ee);
		}
		String entry_name = relative_path + File.separator + file_name;
		entry_name = Utilities.replaceAllSubString(entry_name, File.separator,"/");
		ZipEntry e = new ZipEntry(entry_name);
		e.setTime(file.lastModified());
		try{
			output.putNextEntry(e);
			int len=0;
		    while((len=in.read(b)) != -1) {
		    	output.write(b,0,len);
		    }
		    output.closeEntry();
		    in.close();
		}catch(IOException ee){
			throw new SDXException(ee.getMessage(),ee);
		} 
	}

}
