package com.mortals.xhx.common.utils;

import cn.hutool.core.compress.Gzip;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ZipUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
import org.apache.commons.io.IOUtils;
import org.codehaus.plexus.archiver.tar.TarGZipUnArchiver;
import org.codehaus.plexus.logging.console.ConsoleLoggerManager;

import java.io.*;
import java.util.HashSet;
import java.util.Set;
import java.util.zip.GZIPInputStream;

@Slf4j
public class ZipUtils {

    public static Set<String> localFiles = null;

    /**
     * 解压tar.gz压缩包
     *
     * @param fileName
     * @param unZipPath
     * @return
     */
    public static Set<String> unGzip(String fileName, String unZipPath) {
        Set<String> set = new HashSet<>();
        try {

            InputStream inputStream = FileUtil.getInputStream(fileName);
            TarArchiveInputStream fin = new TarArchiveInputStream(new GzipCompressorInputStream(inputStream));
            log.info("********开始执行gzip");
            TarArchiveEntry entry;
            // 将 tar 文件解压到 extractPath 目录下
            while ((entry = fin.getNextTarEntry()) != null) {
                if (entry.isDirectory()) {
                    continue;
                }
                //目标文件位置
                File curfile = new File(unZipPath + entry.getName());
                File parent = curfile.getParentFile();
                log.info("***文件保存的路径" + curfile.getAbsolutePath());
                if (!parent.exists()) {
                    parent.mkdirs();
                }
                // 将文件写出到解压的目录
                IOUtils.copy(fin, new FileOutputStream(curfile));
                set.add(curfile.getAbsolutePath());
            }


        } catch (IOException e) {
            e.printStackTrace();
        }
        if (localFiles == null) {
            localFiles = set;
        } else {
            localFiles.addAll(set);
        }

        return set;
    }


    /**
     * 解压tar.gz压缩包
     *
     * @param inputStream
     * @param unZipPath
     * @return
     */
    public static Set<String> unGzip(InputStream inputStream, String unZipPath) {
        Set<String> set = new HashSet<>();
        TarArchiveInputStream fin =null;
      //  FileOutputStream fileOutputStream =null;
        GzipCompressorInputStream gzipCompressorInputStream = null;
        try {
             gzipCompressorInputStream = new GzipCompressorInputStream(inputStream);

            fin = new TarArchiveInputStream(gzipCompressorInputStream);

            log.info("********开始执行gzip");
            TarArchiveEntry entry;
            // 将 tar 文件解压到 extractPath 目录下
            while (fin!=null&&fin.getNextTarEntry() != null) {
                entry= fin.getNextTarEntry();
                if(entry==null) continue;
                if (entry.isDirectory()) {
                    continue;
                }
                //目标文件位置
                File curfile = new File(unZipPath + entry.getName());
                File parent = curfile.getParentFile();
                log.info("***文件保存的路径" + curfile.getAbsolutePath());
                if (!parent.exists()) {
                    parent.mkdirs();
                }
                // 将文件写出到解压的目录
                if(fin!=null){
                    FileUtil.writeFromStream(fin,curfile);
                }

                //fileOutputStream = new FileOutputStream(curfile);
                //IOUtils.copy(fin, fileOutputStream);
                //set.add(curfile.getAbsolutePath());
            }

        } catch (IOException e) {
            log.error("解压tar.gz文件失败", e);
        }finally {
            try {
                inputStream.close();
                fin.close();
               // fileOutputStream.close();
                gzipCompressorInputStream.close();
            } catch (IOException e) {
                log.error("关闭流失败", e);
            }
        }
//        if (localFiles == null) {
//            localFiles = set;
//        } else {
//            localFiles.addAll(set);
//        }

        return set;
    }



    // 解压tar包
    public Set<String> unTar(String fileName, String unZipPath) {
        Set<String> set = new HashSet<>();
        InputStream inputStream =null;
        TarArchiveInputStream fin =null;
        try  {
             inputStream = FileUtil.getInputStream(fileName);

             fin = new TarArchiveInputStream(inputStream);
            log.info("********开始执行tar");
            // File extraceFolder = new File(unZipPath);
            TarArchiveEntry entry;

            // 将 tar 文件解压到 extractPath 目录下
            while ((entry = fin.getNextTarEntry()) != null) {
                if (entry.isDirectory()) {
                    continue;
                }
               log.info("*********创建目录开始" + unZipPath);
                boolean flag = FileUtil.exist(unZipPath);
               log.info("***********解压目录创建结束" + flag);
               log.info("***文件名称" + entry.getName());
                File curfile = new File(unZipPath + entry.getName());
                File parent = curfile.getParentFile();
               log.info("***文件保存的路径" + curfile.getAbsolutePath());
                if (!parent.exists()) {
                    parent.mkdirs();
                }
                set.add(curfile.getAbsolutePath());
                // 将文件写出到解压的目录
                IOUtils.copy(fin, new FileOutputStream(curfile));
            }

            //fin.close();


        } catch (IOException e) {
           log.error("解压tar文件失败", e);
        }finally {
            try {
                fin.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            try {
                inputStream.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        if (localFiles == null) {
            localFiles = set;
        } else {
            localFiles.addAll(set);
        }

        return set;
    }


    private static final int BUFFER_SIZE = 1024;

    /**
     * 解压 gzip 文件
     *
     * @param input
     * @param output
     *
     */
    public static void decompressGzip(File input, File output) throws IOException {
        try (GZIPInputStream in = new GZIPInputStream(new FileInputStream(input))) {
            try (FileOutputStream out = new FileOutputStream(output)) {
                byte[] buffer = new byte[BUFFER_SIZE];
                int len;
                while((len = in.read(buffer)) != -1) {
                    out.write(buffer, 0, len);
                }
            }
        }
    }

    /**
     * 解压 tar.gz 文件到指定目录
     *
     * @param tarGzFile  tar.gz 文件路径
     * @param destDir  解压到 destDir 目录，如果没有则自动创建
     *
     */
    public static void extractTarGZ(File tarGzFile, String destDir) throws IOException {

        GzipCompressorInputStream gzipIn = new GzipCompressorInputStream(new FileInputStream(tarGzFile));
        try (TarArchiveInputStream tarIn = new TarArchiveInputStream(gzipIn)) {
            TarArchiveEntry entry;

            while ((entry = (TarArchiveEntry) tarIn.getNextEntry()) != null) {

           
                if (entry.isDirectory()) {
                    File f = new File(destDir + "/" + entry.getName());
                    boolean created = f.mkdirs();
                    if (!created) {
                        System.out.printf("Unable to create directory '%s', during extraction of archive contents.\n",
                                f.getAbsolutePath());
                    }
                } else {
                    int count;
                    byte [] data = new byte[BUFFER_SIZE];

                    FileOutputStream fos = new FileOutputStream(destDir + "/" + entry.getName(), false);
                    try (BufferedOutputStream dest = new BufferedOutputStream(fos, BUFFER_SIZE)) {
                        while ((count = tarIn.read(data, 0, BUFFER_SIZE)) != -1) {
                            dest.write(data, 0, count);
                        }
                    }
                }
            }
        }
    }

    public static void main(String[] args) throws IOException {
        String fileName = "E:\\pic\\zip\\base-manager.tar.gz";

        String unZipPath = "E:\\pic\\zip\\";

        File destDir = new File(unZipPath);

        //ZipUtils.unGzip(fileName, unZipPath);
        File sourceFile = new File(fileName);

  /*      File file = new File(fileName);
       ;
        byte[] bytes = ZipUtil.unGzip(FileUtil.readBytes(file));*/

/*        ZipUtils.extractTarGZ(file, unZipPath);*/


        final TarGZipUnArchiver ua = new TarGZipUnArchiver();
// Logging - as @Akom noted, logging is mandatory in newer versions, so you can use a code like this to configure it:
        ConsoleLoggerManager manager = new ConsoleLoggerManager();
        manager.initialize();
        ua.enableLogging(manager.getLoggerForComponent("bla"));
// -- end of logging part
        ua.setSourceFile(sourceFile);
        destDir.mkdirs();
        ua.setDestDirectory(destDir);
        ua.extract();


    }

}
