package com.yxcheng.token.utils;

import net.lingala.zip4j.core.ZipFile;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.io.ZipOutputStream;
import net.lingala.zip4j.model.FileHeader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipEntry;


/**
* @describe：解压zip文件
* @author： caoxiaohong
*/
public class ZipDecompress  {

    protected static final Logger logger = LoggerFactory.getLogger(ZipDecompress.class);

    public static String SUCCESS = "0";
    public static String UN_DECOMPRESS = "1";
    public static String WRONG_PASSWORD = "2";


    public static void zip(File target, byte[] bytes) {
        ByteArrayInputStream bais = null;
        ZipOutputStream zos = null;
        try {
            zos = new ZipOutputStream(new FileOutputStream(target));
            bais = new ByteArrayInputStream(bytes);

            byte[] buffer = new byte[2048];
            int count = 0;
            while((count = bais.read(buffer)) >0){
                zos.write(buffer);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally{
            try {
                if(zos != null){
                    zos.close();
                }
                if(bais!=null){
                    bais.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    /*
          获取ZIP文件中的文件名和目录名
          */
    public void getEntryNames(String zipFilePath, String password){
        List<String> entryList = new ArrayList<String>();
        ZipFile zf;
        try {
            zf = new ZipFile(zipFilePath);
            zf.setFileNameCharset("gbk");//默认UTF8，如果压缩包中的文件名是GBK会出现乱码
            if(zf.isEncrypted()){
                zf.setPassword(password);//设置压缩密码
            }
            for(Object obj : zf.getFileHeaders()){
                FileHeader fileHeader = (FileHeader)obj;
                String fileName = fileHeader.getFileName();//文件名会带上层级目录信息
                entryList.add(fileName);
            }
        } catch (ZipException e) {
            e.printStackTrace();
        }

    }


    /*
    将ZIP包中的文件解压到指定目录
    */
    public static String extract(String uuidFlag, String taxno, String zipFilePath, String password, File destFile, String doc){
        String extractResult = SUCCESS;
        InputStream is = null;
        java.util.zip.ZipOutputStream zos = null;
        ZipFile zf;
        try {
            zf = new ZipFile(zipFilePath);
            zf.setFileNameCharset("gbk");
            if (!zf.isValidZipFile()) {
                // 验证.zip文件是否合法，包括文件是否存在、是否为zip文件、是否被损坏等
                throw new ZipException("压缩文件不合法,可能被损坏.");
            }
            if(zf.isEncrypted()){
                zf.setPassword(password);
            }
            zos = new java.util.zip.ZipOutputStream(new FileOutputStream(destFile));
            int i=1;
            for(Object obj : zf.getFileHeaders()){
                FileHeader fileHeader = (FileHeader)obj;
                if(!destFile.getParentFile().exists()){
                    destFile.getParentFile().mkdirs();//创建目录
                }
                is = zf.getInputStream(fileHeader);
                zos.putNextEntry(new ZipEntry(getZipName(zipFilePath) + "-"+ i +"." + doc));
                int readLen = -1;
                byte[] buff = new byte[4096];
                while ((readLen = is.read(buff)) != -1) {
                    zos.write(buff,0,readLen);
                }
                is.close();
                zos.flush();
                zos.closeEntry();
                i++;
            }
        }catch (Exception e){
            String msg = e.getMessage();
            logger.error(uuidFlag + " taxno is " + taxno + ", file path is " + zipFilePath + " Zip extract " +msg);
            extractResult = executeExtractMsg(msg);
        }finally{
            //关闭资源
            try{
                if(is != null){
                    is.close();
                }
            }catch(IOException ioe){
                ioe.printStackTrace();
                logger.error(uuidFlag + " taxno is " + taxno + " IS close is error!" + ioe.getMessage());
            }
            try{
                if(zos!=null){
                    zos.close();
                }
            }catch(IOException ioe){
                ioe.printStackTrace();
                logger.error(uuidFlag + " taxno is " + taxno + " ZOS close is error!" + ioe.getMessage());
            }
        }
        return extractResult;
    }

    private static String executeExtractMsg(String msg) {
        if(msg.contains("Wrong Password")){
            return WRONG_PASSWORD;
        }
        return UN_DECOMPRESS;
    }

    public static String getOriginName(String fileName){
        int start = fileName.lastIndexOf(File.separator);
        if(start <0) start = 0;
        int end = fileName.lastIndexOf(".");
        return fileName.substring(start,end);
    }

    public static String getZipName(String fileName){
        int start = fileName.lastIndexOf(File.separator);
        int end = fileName.lastIndexOf(".");
        return fileName.substring(start +1,end);
    }

}
