package cn.estsh.i3plus.core.apiservice.util;

import cn.estsh.i3plus.pojo.platform.bean.SysUserInfo;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipFile;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * @Description :
 * 压缩或解压zip：由于直接使用java.util.zip工具包下的类，会出现中文乱码问题，
 * 所以使用ant.jar中的org.apache.tools.zip下的工具类
 * @Reference :
 * @Author : yunhao
 * @CreateDate : 2019-01-11 10:16
 * @Modify:
 **/
public class ZipUtil {

    public static final Logger LOGGER = LoggerFactory.getLogger(ZipUtil.class);

    private static byte[] _byte = new byte[1024];

    /**
     * 压缩文件或路径
     *
     * @param zip      压缩的目的地址
     * @param srcFiles 压缩的源文件
     */
    public static File zipFile(String zip, List<File> srcFiles) {
        try {
            // zip == null 则创建临时文件
            if(StringUtils.isBlank(zip)){
                zip = File.createTempFile("zip" + new Date().getTime(), ".zip").getPath();
            }
            File zipFile = new File(zip);
            if (zip.endsWith(".zip") || zip.endsWith(".ZIP")) {
                ZipOutputStream _zipOut = new ZipOutputStream(new FileOutputStream(zipFile));
                for (File _f : srcFiles) {
                    handlerFile(zip, _zipOut, _f, "");
                }
                _zipOut.close();
            } else {
                LOGGER.error("target file[" + zip + "] is not .zip type file");
            }
            return zipFile;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 压缩文件或路径
     *
     * @param zip      压缩的目的地址
     * @param srcFiles 压缩的源文件
     */
    public static File zipFile(String zip, File srcFiles) {
        try {
            File zipFile = null;
            // zip == null 则创建临时文件
            if(StringUtils.isBlank(zip)){
                zipFile = new File(System.getProperty("java.io.tmpdir") + File.separator + SysUserInfo.class.getSimpleName()+ ".zip");
                zipFile.createNewFile();
                zip = zipFile.getPath();
            }
            if (zip.endsWith(".zip") || zip.endsWith(".ZIP")) {
                zipFile = new File(zip);
                ZipOutputStream _zipOut = new ZipOutputStream(new FileOutputStream(zipFile));
                handlerFile(zip, _zipOut, srcFiles, "");
                _zipOut.close();
            } else {
                LOGGER.error("target file[" + zip + "] is not .zip type file");
            }
            return zipFile;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * @param zip     压缩的目的地址
     * @param zipOut
     * @param srcFile 被压缩的文件信息
     * @param path    在zip中的相对路径
     * @throws IOException
     */
    private static void handlerFile(String zip, ZipOutputStream zipOut, File srcFile, String path) throws IOException {
        LOGGER.debug(" begin to compression file[" + srcFile.getName() + "]");
        if (!"".equals(path) && !path.endsWith(File.separator)) {
            path += File.separator;
        }
        if (!srcFile.getPath().equals(zip)) {
            // 判断是否为文件目录如果为文件目录则打包目录下所有文件
            if (srcFile.isDirectory()) {
                File[] _files = srcFile.listFiles();
                if (_files.length == 0) {
                    zipOut.putNextEntry(new ZipEntry(path + srcFile.getName() + File.separator));
                    zipOut.closeEntry();
                } else {
                    for (File _f : _files) {
                        handlerFile(zip, zipOut, _f, path + srcFile.getName());
                    }
                }
            } else {
                InputStream _in = new FileInputStream(srcFile);
                zipOut.putNextEntry(new ZipEntry(path + srcFile.getName()));
                int len = 0;
                while ((len = _in.read(_byte)) > 0) {
                    zipOut.write(_byte, 0, len);
                }
                _in.close();
                zipOut.closeEntry();
            }
        }
    }

    /**
     * 解压缩ZIP文件，将ZIP文件里的内容解压到targetDIR目录下
     *
     * @param zipPath 待解压缩的ZIP文件路径
     * @param descDir 目标目录
     */
    public static List<File> upzipFile(String zipPath, String descDir) {
        return upzipFile(new File(zipPath), descDir);
    }

    /**
     * 对.zip文件进行解压缩
     *
     * @param zipFile 解压缩文件
     * @param descDir 压缩的目标地址，如：D:\\测试 或 /mnt/d/测试
     * @return
     */
    @SuppressWarnings("rawtypes")
    public static List<File> upzipFile(File zipFile, String descDir) {
        List<File> _list = new ArrayList<>();
        try {
            ZipFile _zipFile = new ZipFile(zipFile);
            for (Enumeration entries = _zipFile.getEntries(); entries.hasMoreElements(); ) {
                ZipEntry entry = (ZipEntry) entries.nextElement();
                File _file = new File(descDir + File.separator + entry.getName());
                if (entry.isDirectory()) {
                    _file.mkdirs();
                } else {
                    File _parent = _file.getParentFile();
                    if (!_parent.exists()) {
                        _parent.mkdirs();
                    }
                    InputStream _in = _zipFile.getInputStream((ZipArchiveEntry) entry);
                    OutputStream _out = new FileOutputStream(_file);
                    int len;
                    while ((len = _in.read(_byte)) > 0) {
                        _out.write(_byte, 0, len);
                    }
                    _in.close();
                    _out.flush();
                    _out.close();
                    _list.add(_file);
                }
            }
        } catch (IOException e) {
        }
        return _list;
    }
}
