package com.xypower.common;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.WritableByteChannel;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class ZipUtils {

    public static void ZipFolder(File srcDirectory, File zipFile, FilenameFilter filter) {
        ZipOutputStream outZip = null;
        WritableByteChannel writableByteChannel = null;
        FileInputStream inputStream = null;
        FileOutputStream fileOutputStream = null;

        try {
            fileOutputStream = new FileOutputStream(zipFile);
            outZip = new ZipOutputStream(fileOutputStream);

            writableByteChannel = Channels.newChannel(outZip);

            ZipEntry zipEntry = null;

            File[] subFiles = srcDirectory.listFiles(filter);
            if (subFiles != null && subFiles.length > 0) {
                for (File subFile : subFiles) {
                    zipEntry = new ZipEntry(subFile.getName());
                    outZip.putNextEntry(zipEntry);

                    inputStream = new FileInputStream(subFile);

                    FileChannel fileChannel = inputStream.getChannel();
                    try {
                        fileChannel.transferTo(0, fileChannel.size(), writableByteChannel);
                    } finally {
                        FilesUtils.closeFriendly(fileChannel);
                    }
                    FilesUtils.closeFriendly(inputStream);

                    outZip.closeEntry();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            FilesUtils.closeFriendly(inputStream);
            try {
                outZip.finish();
            } catch (Exception ex) {
                ex.printStackTrace();
            }
            FilesUtils.closeFriendly(fileOutputStream);
            FilesUtils.closeFriendly(writableByteChannel);
            FilesUtils.closeFriendly(outZip);
        }
    }

    public static void ZipFolders(Map<String, File> srcDirectories, File zipFile, FilenameFilter filter) {
        ZipOutputStream outZip = null;
        WritableByteChannel writableByteChannel = null;
        FileInputStream inputStream = null;
        FileOutputStream fileOutputStream = null;

        try {
            fileOutputStream = new FileOutputStream(zipFile);
            outZip = new ZipOutputStream(fileOutputStream);
            writableByteChannel = Channels.newChannel(outZip);

            ZipEntry zipEntry = null;

            for (Map.Entry<String, File> srcDirectory : srcDirectories.entrySet()) {
                File[] subFiles = srcDirectory.getValue().listFiles(filter);
                if (subFiles == null || subFiles.length == 0) {
                    continue;
                }
                for (File subFile : subFiles) {
                    zipEntry = new ZipEntry(srcDirectory.getKey() + File.separator + subFile.getName());
                    outZip.putNextEntry(zipEntry);

                    inputStream = new FileInputStream(subFile);

                    FileChannel fileChannel = inputStream.getChannel();
                    try {
                        fileChannel.transferTo(0, fileChannel.size(), writableByteChannel);
                    } finally {
                        FilesUtils.closeFriendly(fileChannel);
                    }
                    FilesUtils.closeFriendly(inputStream);

                    outZip.closeEntry();
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            FilesUtils.closeFriendly(inputStream);
            try {
                outZip.finish();
            } catch (Exception ex) {
                ex.printStackTrace();
            }

            FilesUtils.closeFriendly(fileOutputStream);
            FilesUtils.closeFriendly(writableByteChannel);
            FilesUtils.closeFriendly(outZip);
        }
    }

    public static void ZipFiles(List<String> srcFiles, File zipFile) {

        ZipOutputStream outZip = null;
        WritableByteChannel writableByteChannel = null;
        FileInputStream inputStream = null;
        FileOutputStream fileOutputStream = null;
        try {
            fileOutputStream = new FileOutputStream(zipFile);
            outZip = new ZipOutputStream(fileOutputStream);
            writableByteChannel = Channels.newChannel(outZip);

            for (String path : srcFiles) {
                File file = new File(path);
                if (!file.exists()) {
                    continue;
                }
                ZipEntry zipEntry = new ZipEntry(srcFiles.size() > 1 ? path.substring(1) : file.getName());
                outZip.putNextEntry(zipEntry);

                inputStream = new FileInputStream(file);
                FileChannel fileChannel = inputStream.getChannel();
                try {
                    fileChannel.transferTo(0, fileChannel.size(), writableByteChannel);
                } finally {
                    FilesUtils.closeFriendly(fileChannel);
                }

                outZip.closeEntry();
                FilesUtils.closeFriendly(inputStream);
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            FilesUtils.closeFriendly(inputStream);
            if (outZip != null) {
                try {
                    outZip.finish();
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
            FilesUtils.closeFriendly(fileOutputStream);
            FilesUtils.closeFriendly(writableByteChannel);
            FilesUtils.closeFriendly(outZip);
        }
    }
}
