package vut.msa.utilities;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.zip.Adler32;
import java.util.zip.CheckedOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
import org.apache.log4j.Logger;

/**
 * Trieda poskytuje metody na kompresiu a dekompresiu suborov pomocou ZIP.
 */
public final class ZipUtilities {

    private static final Logger log = Logger.getLogger(ZipUtilities.class);
    private static final int BUFFER = 2048;

    /**
     * Metoda zkomprimuje subory do ZIP archivu. V sucasnosti ma problem s
     * diakritikou v nazvoch suboru, teraz vie pracovat len so subormi bez
     * diakritiky v nazve,
     *
     * @param files zoznam suborov, ktore maju byt zkomprimovane
     * @param zipFileName nazov ZIP suboru, do ktoreho maju byt subory zbalene
     */
    public static void compress(ArrayList<String> files, String zipFileName) {
        try {

            BufferedInputStream source = null;
            FileOutputStream destination = new FileOutputStream(zipFileName);

            CheckedOutputStream checksum = new CheckedOutputStream(destination, new Adler32());
            ZipOutputStream zipOut = new ZipOutputStream(new BufferedOutputStream(checksum));

            byte[] data = new byte[BUFFER];
            Iterator<String> iterator = files.iterator();
            while (iterator.hasNext()) {
                File file = new File(iterator.next());
                log.info("Komprimujem subor: " + file.getName());
                FileInputStream fi = new FileInputStream(file);
                source = new BufferedInputStream(fi, BUFFER);

                //DO archivu ulozim celu cestu, aby pri obnove bol v rovnakej adr. strukture
                ZipEntry entry = new ZipEntry(file.getAbsolutePath());
                zipOut.putNextEntry(entry);

                int count;
                while ((count = fi.read(data, 0, BUFFER)) != -1) {
                    zipOut.write(data, 0, count);
                }
                source.close();
            }

            zipOut.close();
            log.info("Checksum archivu: " + checksum.getChecksum().getValue());
        } catch (Exception ex) {
            log.error("Nastala chyba pri komprimacii." + ex.getMessage());
        }

    }

    /**
     * Metoda spocita pocet zaznamov (dokumentov) v ulozenom archive.
     *
     * @param fileName cesta k archivu
     * @return pocet zaznamov v archive
     */
    public static int countFilesInZip(String fileName) {

        int count = 0;
        try {
            
            ZipInputStream zin = new ZipInputStream(
                    new FileInputStream(fileName));
            ZipEntry entry;
            while ((entry = zin.getNextEntry()) != null) {
                count++;
                zin.closeEntry();
            }
            zin.close();
            log.info("Archiv: " + fileName + " ma zaznamov: " + count);
        } catch (Exception ex) {
            log.error("Nie je mozne zratat subory v archive.");
            ex.printStackTrace();
        }

        return count;
    }
}
