package com.reyun.saas.common.util;

import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

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

/**
 * description:
 *
 * @author nolan
 * @date 07/12/2017
 */
public class CompressUtil {
    private static Logger logger = LoggerFactory.getLogger(CompressUtil.class);

    public static ByteArrayOutputStream createTarGz(String fileName, String subFileName, byte[] subContent) throws Exception {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        TarArchiveOutputStream gzOut = null;
        try {
            gzOut = new TarArchiveOutputStream(
                    new GZIPOutputStream(
                            byteArrayOutputStream
                    ));

            TarArchiveEntry tarArchiveEntry = new TarArchiveEntry(subFileName);
            tarArchiveEntry.setSize(subContent.length);
            gzOut.setLongFileMode(TarArchiveOutputStream.LONGFILE_POSIX);
            gzOut.putArchiveEntry(tarArchiveEntry);
            gzOut.write(subContent);
            gzOut.closeArchiveEntry();
            return byteArrayOutputStream;
        } finally {
            if (gzOut != null) {
                try {
                    gzOut.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (byteArrayOutputStream != null) {
                IOUtil.close(byteArrayOutputStream);
            }
        }
    }

    /**
     *
     * @Title: compress
     * @Description: 将文件用tar压缩
     * @param source
     *            需要压缩的文件
     * @return File 返回压缩后的文件
     * @throws
     */
    public static File compress(File source) {
        String archive = archive(source.getAbsolutePath());
        String s = compressArchive(archive);
        new File(archive).delete();
        return new File(s);
    }

    public static void main(String[] args) {
        List<File> files = new ArrayList<>();
        File file = new File("D:\\s3_downlod_test_save\\0e75b2ec01218305f4fc1ed16523a232_全部_2019-04-30_2019-05-06.txt");
        files.add(file);
        CompressUtil.compress(file);
    }

    /**
     * 归档
     * @param entry
     * @throws IOException
     * @author yutao
     * @return
     * @date 2017年5月27日下午1:48:23
     */
    private static String archive(String entry){
        File file = new File(entry);
        TarArchiveOutputStream tos=null;
        try { tos = new TarArchiveOutputStream(new FileOutputStream(file.getAbsolutePath().replace(".csv","") + ".tar"));
        String base = file.getName();

            if(file.isDirectory()){
                archiveDir(file, tos, base);
            }else{
                archiveHandle(tos, file, base);
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            try {
                tos.close();
            }catch (Exception e1){
                e1.printStackTrace();
            }
        }

        return file.getAbsolutePath().replace(".csv","") + ".tar";
    }

    /**
     * 递归处理，准备好路径
     * @param file
     * @param tos
     * @throws IOException
     * @author yutao
     * @date 2017年5月27日下午1:48:40
     */
    private static void archiveDir(File file, TarArchiveOutputStream tos, String basePath) throws IOException {
        File[] listFiles = file.listFiles();
        for(File fi : listFiles){
            if(fi.isDirectory()){
                archiveDir(fi, tos, basePath + File.separator + fi.getName());
            }else{
                archiveHandle(tos, fi, basePath);
            }
        }
    }

    /**
     * 具体归档处理（文件）
     * @param tos
     * @param fi
     * @throws IOException
     * @author yutao
     * @date 2017年5月27日下午1:48:56
     */
    private static void archiveHandle(TarArchiveOutputStream tos, File fi, String basePath) throws IOException {
        TarArchiveEntry tEntry = new TarArchiveEntry(basePath);
        tEntry.setSize(fi.length());
        tos.setLongFileMode(TarArchiveOutputStream.LONGFILE_POSIX);//设置长文件模式
        tos.setBigNumberMode(TarArchiveOutputStream.BIGNUMBER_POSIX);//设置大数字模式
        tos.putArchiveEntry(tEntry);
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(fi));

        byte[] buffer = new byte[1024];
        int read = -1;
        while((read = bis.read(buffer)) != -1){
            tos.write(buffer, 0 , read);
        }
        bis.close();
        tos.closeArchiveEntry();//这里必须写，否则会失败
    }

    /**
     * 把tar包压缩成gz
     * @param path
     * @throws IOException
     * @author yutao
     * @return
     * @date 2017年5月27日下午2:08:37
     */
    public static String compressArchive(String path){
        BufferedInputStream bis =null;
        GzipCompressorOutputStream gcos=null;
        try {
            bis = new BufferedInputStream(new FileInputStream(path));

            gcos = new GzipCompressorOutputStream(new BufferedOutputStream(new FileOutputStream(path + ".gz")));

        byte[] buffer = new byte[1024];
        int read = -1;
            while((read = bis.read(buffer)) != -1){
                gcos.write(buffer, 0, read);
            }

        }catch (Exception e){
            e.printStackTrace();
        }finally {
            try {
                gcos.close();
                bis.close();
            }catch (Exception e1){
                e1.printStackTrace();
            }
        }

        return path + ".gz";
    }
}
