package com.fidufosyga.model;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

/**
 * @author Yes Created on 15 de Mayo de 2008, 12:37 PM
 */
public class Zip {

	/** Creates a new instance of jzip */
	// EACG.INI.BDUA_SII.04/02/2009.Ajustando para comprimir lo maximo.
	// int BUFFER_SIZE = 8192;
	int BUFFER_SIZE = 32768;
	// EACG.FIN.BDUA_SII.04/02/2009.
	String filename, controlfile;
	boolean esValidable = false;

	public Zip(String fn) {
		filename = fn;
		if (fn != null)
			esValidable = Validable();
	}

	public String ExtraerNombre(String ruta, String sep) {
		for (int i = ruta.length() - 1; i > 0; i--) {
			if (ruta.substring(i - 1, i).compareTo(sep) == 0)
				return ruta.substring(i);
		}
		return ruta;
	}

	public void Comprimir(List<String> files) {

		try {

			// Reference to the file we will be adding to the zipfile
			BufferedInputStream origin = null;

			// Reference to our zip file
			FileOutputStream dest = new FileOutputStream(filename);

			// Wrap our destination zipfile with a ZipOutputStream
			ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(dest));

			// Create a byte[] buffer that we will read data from the source
			// files into and then transfer it to the zip file
			byte[] data = new byte[BUFFER_SIZE];

			// Iterate over all of the files in our list
			for (Iterator<String> i = files.iterator(); i.hasNext();) {

				// Get a BufferedInputStream that we can use to read the source
				// file
				String nombreArchivo = (String) i.next();
				System.out.println("Adding: " + nombreArchivo);
				
				File archivotmp = new File(nombreArchivo);
				FileInputStream fi = new FileInputStream(nombreArchivo);
				origin = new BufferedInputStream(fi, BUFFER_SIZE);
				System.out.println("Original: " + archivotmp.getName());
				// Setup the entry in the zip file
				ZipEntry entry = new ZipEntry(archivotmp.getName());
				out.putNextEntry(entry);

				// Read data from the source file and write it out to the zip
				// file
				int count;
				while ((count = origin.read(data, 0, BUFFER_SIZE)) != -1) {
					out.write(data, 0, count);
				}

				// Close the source file
				origin.close();
			}

			// Close the zip file
			out.close();
			dest.close();

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public List<String> Descomprimir(String destination) {

		try {
			// Archivos descomprimidos
			List<String> lZip = new ArrayList<String>();

			// Create a ZipInputStream to read the zip file
			BufferedOutputStream dest = null;
			FileInputStream fis = new FileInputStream(filename);
			ZipInputStream zis = new ZipInputStream(
					new BufferedInputStream(fis));

			// Loop over all of the entries in the zip file
			int count;
			byte data[] = new byte[BUFFER_SIZE];
			ZipEntry entry;
			while ((entry = zis.getNextEntry()) != null) {
				if (!entry.isDirectory()) {
					// String entryName = entry.getName();
					// prepareFileDirectories( destination, entryName );
					// System.out.println(destination);
					// System.out.println(File.separator);
					// System.out.println(entry.getName());
					// System.out.println(ExtraerNombre(entry.getName(),File.separator));
					if (!destination.endsWith(File.separator))
						destination = destination + File.separator;
					String destFN = destination
							+ ExtraerNombre(entry.getName(), File.separator);
					// System.out.println(destFN);
					lZip.add(destFN);
					// Write the file to the file system
					FileOutputStream fos = new FileOutputStream(destFN);
					dest = new BufferedOutputStream(fos, BUFFER_SIZE);
					while ((count = zis.read(data, 0, BUFFER_SIZE)) != -1) {
						dest.write(data, 0, count);
					}
					dest.flush();
					dest.close();
				}
			}
			zis.close();
			return lZip;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	public List<String> ListarNombreArchivos() {

		List<String> lZip = new ArrayList<String>();
		try {
			FileInputStream fis = new FileInputStream(filename);
			ZipInputStream zis = new ZipInputStream(
					new BufferedInputStream(fis));
			// Loop over all of the entries in the zip file
			ZipEntry entry;
			while ((entry = zis.getNextEntry()) != null) {
				if (!entry.isDirectory()) {
					lZip.add(entry.getName());
					System.out.println(entry.getName());
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
		return lZip;
	}

	public List<ItemZip> Listar() {
		try {
			FileInputStream fis = new FileInputStream(filename);
			ZipInputStream zis = new ZipInputStream(
					new BufferedInputStream(fis));
			// Loop over all of the entries in the zip file
			ZipEntry entry;
			DateFormat df = DateFormat.getDateTimeInstance(DateFormat.SHORT,
					DateFormat.SHORT);
			List<ItemZip> lZip = new ArrayList<ItemZip>();
			while ((entry = zis.getNextEntry()) != null) {
				if (!entry.isDirectory()) {
					ItemZip n = new ItemZip(ExtraerNombre(entry.getName(),
							File.separator),
							df.format(new Date(entry.getTime())),
							entry.getSize());
					lZip.add(n);
					System.out.println(entry.getSize());
					System.out.println(n.getDatos());
				}
			}
			return lZip;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	private boolean Validable() {
		// El archivo es un zip valido si inicia con los caracteres 'RP' seguido
		// por el numero de remision. ej: RP1100087

		// if(!filename.equals("RP" + numRem + ".zip")) return false;

		// Verifica ahora que el arcivo .zip contenga un archivo de control, es
		// decir CT + numero de remision. ej: CT1100087
		/*
		 * ListaItem lZip = Listar(); lZip.Primero(); for(ItemZip itzip =
		 * (ItemZip)lZip.getNextItem();itzip != null;itzip =
		 * (ItemZip)lZip.getNextItem())
		 * if(itzip.getLlave().substring(0,2).equals("CT")){ controlfile =
		 * itzip.getLlave(); return true; }
		 */
		return false;
	}

	public boolean Eliminar() {
		File archivo = new File(filename);
		return archivo.delete();
	}

	public boolean esValido() {
		return esValidable;
	}

	public String getPath() {
		return filename;
	}

	public String getArchivoCT() {
		return controlfile;
	}

	/**
	 * @author Yes
	 */
	/** Esta clase es una representacion de un archivo comprimido ZIP */
	public class ItemZip {
		String fecha;
		String nombre;
		long tam;

		/** Crea una nueva instancia de Ripzip */
		public ItemZip(String nom, String f, long t) {
			nom = nombre;
			fecha = f;
			tam = t;
		}

		/** Obtiene un String con el nombre y el tama�o del archivo */
		public String getDatos() {
			return nombre + " " + tam + " bytes ";
		}

		/** Obtiene el nombre del archivo comprimido */
		public String getNombre() {
			return nombre;
		}

		/** Obtiene el tama�o del archivo */
		public long getTam() {
			return tam;
		}
	}
//
//	/**
//	 * @param args
//	 */
//	public static void main(String[] args) {
//		// TODO Auto-generated method stub
//
//		Zip compresion = new Zip("E:\\Resultados\\paquete.zip");
//		ArrayList<String> archivos = new ArrayList<String>();
//		archivos.add("E:\\Resultados\\FURIPS112345678901234567890.txt");
//		archivos.add("E:\\Resultados\\furips212345678901234567890.TXT");
//		archivos.add("E:\\Resultados\\FURIPS312345678901234567890.txt");
//		compresion.Comprimir(archivos);
//		compresion.Descomprimir("E:\\Resultados\\");
//	}

}