package cn.reghao.bnt.web.devops.builder.tool.packer;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;

import java.io.*;
import java.util.Arrays;
import java.util.Objects;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

/**
 * TODO: 提升压缩和解压性能
 *
 * @author reghao
 * @date 2019-08-27 17:47:36
 */
@Slf4j
public class ZipFiles {
    /**
     * 将目录压缩为一个文件
     *
     * @param
     * @date 2019-08-28 上午12:42
     */
    public static void zip(String src, String dst) throws IOException {
        // TODO: 判断 dst 是否为 src 的子目录
        File srcFile = new File(src);
        if (!srcFile.exists()) {
            log.info("{} 不存在", src);
            return;
        }

        String filePath;
        if (dst.endsWith(".zip")) {
            filePath = dst;
        } else {
            filePath = dst + ".zip";
        }

        File dstFile = new File(filePath);
        if (dstFile.exists() && !dstFile.delete()) {
            log.info("删除 {} 失败", dst);
            return;
        }

        ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(dstFile));
        zipFile(null, srcFile, zipOut);
        zipOut.close();
    }

    /**
     * 将目录中的文件压缩为一个文件
     *
     * @param
     * @return
     * @date 2020-03-11 下午11:12
     */
    public static void zip(File src, String dst) throws IOException {
        // TODO: 判断 dst 是否为 src 的子目录
        String filePath;
        if (dst.endsWith(".zip")) {
            filePath = dst;
        } else {
            filePath = dst + ".zip";
        }
        File dstFile = new File(filePath);
        if (dstFile.exists() && !dstFile.delete()) {
            log.info("删除 {} 失败", dst);
            return;
        }

        ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(dstFile));
        for (File file : Objects.requireNonNull(src.listFiles())) {
            zipFile(null, file, zipOut);
        }

        zipOut.close();
    }

    /**
     * 压缩
     *
     * @param
     * @return
     * @date 2019-08-28 上午12:42
     */
    private static void zipFile(String srcRoot, File file, ZipOutputStream zipOut) {
        if (file == null || !file.exists()) {
            return;
        }

        InputStream in;
        try {
            if (file.isFile()) {
                if (srcRoot == null) {
                    zipOut.putNextEntry(new ZipEntry(file.getName()));
                } else {
                    zipOut.putNextEntry(new ZipEntry(srcRoot + File.separator + file.getName()));
                }

                in = new FileInputStream(file);
                int tmp;
                while ((tmp = in.read()) != -1) {
                    zipOut.write(tmp);
                }
                in.close();
            } else if (file.isDirectory() && Objects.requireNonNull(file.listFiles()).length == 0) {
                if (srcRoot == null) {
                    zipOut.putNextEntry(new ZipEntry(file.getName() + File.separator));
                } else {
                    zipOut.putNextEntry(new ZipEntry(srcRoot + File.separator + file.getName() + File.separator));
                }
            } else {
                File[] files = file.listFiles();
                assert files != null;
                Arrays.asList(files).forEach(file1 -> {
                    if (srcRoot == null) {
                        zipFile(file.getName(), file1, zipOut);
                    } else {
                        zipFile(srcRoot + File.separator + file.getName(), file1, zipOut);
                    }
                });
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 解压到指定目录
     *
     * @param
     * @return
     * @date 2019-08-28 上午12:41
     */
    public static void unzip(String src, String dest) throws IOException {
        File file = new File(src);
        if (!file.exists()) {
            log.info("{} 不存在", src);
            return;
        }

        File destFile = new File(dest);
        if (!destFile.exists()) {
            FileUtils.forceMkdir(destFile);
        }

        java.util.zip.ZipFile zipFile = new java.util.zip.ZipFile(file);
        ZipInputStream zipIn = new ZipInputStream(new FileInputStream(file));
        ZipEntry entry;
        while ((entry = zipIn.getNextEntry()) != null) {
            String filePath = dest + File.separator + entry.getName();
            String dirPath = dirPath(filePath);
            File dir = new File(dirPath);
            if (!dir.exists()) {
                FileUtils.forceMkdir(dir);
            }

            File unzipFile = new File(filePath);
            if (!unzipFile.isDirectory()) {
                InputStream in = zipFile.getInputStream(entry);
                OutputStream out = new FileOutputStream(unzipFile);

                int tmp;
                while ((tmp = in.read()) != -1) {
                    out.write(tmp);
                }
                in.close();
                out.close();
            }
        }
    }

    static String dirPath(String path) {
        int index = path.lastIndexOf(File.separator);
        return path.substring(0, index);
    }
}
