package com.fdkanfang.common.util;

import lombok.extern.log4j.Log4j2;
import org.springframework.util.ResourceUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.Base64;
import java.util.Date;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

/**
 * Created by Owen on 2019/10/25 0025 14:20
 */
@Log4j2
public class FileUtils {


    /**
     * web 文件下载
     * @param response
     * @param path 源文件路径
     * @param path 源文件名
     * @return
     * @throws Exception
     */
    public static void fileDownload(HttpServletResponse response, String path) throws Exception {
        String fileName = path.substring(path.lastIndexOf(File.separator)+1);
        // 当文件名不是英文名的时候，最好使用url解码器去编码一下，
        fileName= URLEncoder.encode(fileName,"UTF-8");

        // 获取response的输出流，用来输出文件
//        ServletOutputStream out = response.getOutputStream();
        OutputStream out = response.getOutputStream();

        // 将响应的类型
        response.setContentType("APPLICATION/OCTET-STREAM");
        response.setHeader("Content-Disposition","attachment; filename="+fileName);

        // 以输入流的形式读取文件
//        log.info("zipPath: " + path);
        FileInputStream in = new FileInputStream(path);

        //可以自己 指定缓冲区的大小
        byte[] buffer = new byte[1024];
        int len = 0;
        while ((len = in.read(buffer)) != -1) {
            out.write(buffer, 0, len);
            out.flush();
        }
        //关闭输入输出流
        out.close();
        in.close();
    }


    /**
     * 获取类路径
     */
    public static String getResource(){
        String path = "";
        try {
            path = ResourceUtils.getURL("classpath:").getPath();
            path = URLDecoder.decode(path,"utf-8");
            log.info("classpath path :"+path);
        } catch (Exception e) {
            log.error(" classpath Error" + e.getMessage(), e);
        }
        return path;
    }


    /**
     * 创建文件夹
     * destDirName：文件夹名称
     */
    public static void createDir(String destDirName) {
        File dir = new File(destDirName);
        // 创建目录
        if (!dir.exists()) {
            dir.mkdirs();
        }
    }

    /**
     * 创建文件夹，如果存在，则先删除，再创建
     * destDirName：文件夹名称
     */
    public static void createDirIfExistThenDel(String destDirName) {
        File dir = new File(destDirName);
        // 创建目录
        if (dir.exists() && dir.isDirectory()) {
            //存在，则先删除，再创建
            deleteDirectory(destDirName);
        }
        createDir(destDirName);

    }

    /**
     * 大文件读写
     *
     * 1.先将文件中的内容读入到缓冲输入流中
     * 2.将输入流中的数据通过缓冲输出流写入到目标文件中
     * 3.关闭输入流和输出流
     *
     * in: 输入流
     * path： 保持位置
     */

    public static int downloanAndGetResolutionRate(InputStream in, String fileFullPath, boolean needCheckResolutin) throws IOException {
        // 输入缓冲流
        File file = new File(fileFullPath);
        if(file.exists()){
            deleteFile(fileFullPath);
            file = new File(fileFullPath);
        }
        BufferedInputStream inputBuff = new BufferedInputStream(in);
        // 输出缓冲流
        BufferedOutputStream stream = new BufferedOutputStream(new FileOutputStream(file));
        int len = 0;
        byte[] buffer = new byte[1024];
        while ((len = inputBuff.read(buffer)) != -1) {
            stream.write(buffer, 0, len);
        }

        stream.flush();
        stream.close();
        inputBuff.close();
        int totalResolutinRate = -1;
        if(needCheckResolutin){
            SimpleImageInfo simpleImageInfo = new SimpleImageInfo(file);
            if(null != simpleImageInfo){
                if(simpleImageInfo.getWidth() <  simpleImageInfo.getHeight()){
                    totalResolutinRate = simpleImageInfo.getHeight();
                }else{
                    totalResolutinRate = simpleImageInfo.getWidth();
                }

            }
        }
        return totalResolutinRate;
    }

    /**
     * 删除单个文件
     *
     * @param fileName 要删除的文件的文件名
     * @return 单个文件删除成功返回true，否则返回false
     */
    public static boolean deleteFile(String fileName) {
        File file = new File(fileName);
        if (file.exists() && file.isFile()) {
            if (file.delete()) {
                return true;
            } else {
                return false;
            }
        } else {
            return false;
        }
    }


    /**
     *
     * @param content base64内容
     * @param path 输出文件路径，需要后缀名
     * @return
     */
    public static  boolean base64ToFileWriter(String content, String path) {
        if (content == null) {
            return false;
        }
        try {
            byte[] b = Base64.getDecoder().decode(content);
            // processing data
            for (int i = 0; i < b.length; ++i) {
                if (b[i] < 0) {
                    b[i] += 256;
                }
            }
            OutputStream out = new FileOutputStream(path);
            out.write(b);
            out.flush();
            out.close();
            return true;
        } catch (Exception e) {
            return false;
        }
    }


    /**
     * 读取文件方法
     * @param Path 文件路径
     * @return 返回内容
     */
    public static String readFile(String Path){
        BufferedReader reader = null;
        String laststr = "";
        try{
            FileInputStream fileInputStream = new FileInputStream(Path);
            InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream, "UTF-8");
            reader = new BufferedReader(inputStreamReader);
            String tempString = null;
            while((tempString = reader.readLine()) != null){
                laststr += tempString;
            }
            reader.close();
        }catch(IOException e){
            e.printStackTrace();
        }finally{
            if(reader != null){
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return laststr;
    }


    /**
     * 生成文件
     * @param content 内容
     * @param path 生成路径
     * @throws IOException
     */
    public static void fileWriter(String content, String path) throws IOException {
        FileWriter writer = new FileWriter(path);
        writer.write(content);
        writer.flush();
        writer.close();
    }

    public static void writeFile(String filePath,String str) throws IOException {
        File fout = new File(filePath);
        if(!fout.getParentFile().exists()){
            fout.getParentFile().mkdirs();
        }
        if(!fout.exists()){
            fout.createNewFile();
        }
        FileOutputStream fos = new FileOutputStream(fout);
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(fos));
        bw.write(str);
        bw.close();
    }

    // 获取时间戳
    public static String timeMillisStr() {
        SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd");
        String format = df.format(new Date());
        long timeMillis = System.currentTimeMillis();
        return format + "_" + timeMillis + "_";
    }

    //返回年月日时分秒
    public static String dateStr() {
        SimpleDateFormat df = new SimpleDateFormat("yyyyMMddhhmmss");
        String format = df.format(new Date());
        return format + "_";
    }

    /**
     * 删除指定文件夹下所有文件
     * @param path 文件夹完整绝对路径
     * @return
     */
    public static boolean delAllFile(String path) {
        boolean flag = false;
        File file = new File(path);
        if (!file.exists()) {
            return flag;
        }
        if (!file.isDirectory()) {
            return flag;
        }
        String[] tempList = file.list();
        File temp = null;
        for (int i = 0; i < tempList.length; i++) {
            if (path.endsWith(File.separator)) {
                temp = new File(path + tempList[i]);
            } else {
                temp = new File(path + File.separator + tempList[i]);
            }
            if (temp.isFile()) {
                temp.delete();
            }
            if (temp.isDirectory()) {
                delAllFile(path + "/" + tempList[i]);//先删除文件夹里面的文件
                delFolder(path + "/" + tempList[i]);//再删除空文件夹
//                delAllFile(path + tempList[i]);//先删除文件夹里面的文件
//                delFolder(path + tempList[i]);//再删除空文件夹
                flag = true;
            }
        }
        return flag;
    }


    /**
     * 根据路径删除指定的目录，无论存在与否
     *
     * @param sPath 要删除的目录path
     * @return 删除成功返回 true，否则返回 false。
     */
    public static boolean deleteFolder(String sPath) {
        boolean flag = false;
        File file = new File(sPath);
        // 判断目录或文件是否存在
        if (!file.exists()) {  // 不存在返回 false
            return flag;
        } else {
            // 判断是否为文件
            if (file.isFile()) {  // 为文件时调用删除文件方法
                return deleteFile(sPath);
            } else {  // 为目录时调用删除目录方法
                return deleteDirectory(sPath);
            }
        }
    }

    /**
     * 删除目录以及目录下的文件
     *
     * @param sPath 被删除目录的路径
     * @return 目录删除成功返回true，否则返回false
     */
    public static boolean deleteDirectory(String sPath) {
        //如果sPath不以文件分隔符结尾，自动添加文件分隔符
        if (!sPath.endsWith(File.separator)) {
            sPath = sPath + File.separator;
        }
        File dirFile = new File(sPath);
        //如果dir对应的文件不存在，或者不是一个目录，则退出
        if (!dirFile.exists() || !dirFile.isDirectory()) {
            return false;
        }
        boolean flag = true;
        //删除文件夹下的所有文件(包括子目录)
        File[] files = dirFile.listFiles();
        for (int i = 0; i < files.length; i++) {
            //删除子文件
            if (files[i].isFile()) {
                flag = deleteFile(files[i].getAbsolutePath());
                if (!flag) {
                    break;
                }
            } //删除子目录
            else {
                flag = deleteDirectory(files[i].getAbsolutePath());
                if (!flag) {
                    break;
                }
            }
        }
        if (!flag) {
            return false;
        }
        //删除当前目录
        if (dirFile.delete()) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 删除文件夹或删除文件
     * @param folderPath 文件夹完整绝对路径
     */
    public static void delFolder(String folderPath) {
        try {

//            File file = new File(folderPath);
//            if (file.exists()){
                //删除完里面所有内容
                delAllFile(folderPath);
                String filePath = folderPath;
                filePath = filePath.toString();
                File myFilePath = new File(filePath);
                //删除空文件夹
                myFilePath.delete();
//            }


        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * zip解压
     * @param zipFileName        zip源文件
     * @param destDirPath     解压后的目标文件夹
     * @throws RuntimeException 解压失败会抛出运行时异常
     */
    public static boolean unzip(String zipFileName, String destDirPath) throws RuntimeException {

        File srcFile = new File(zipFileName);


        long start = System.currentTimeMillis();

        // 判断源文件是否存在

        if (!srcFile.exists()) {

            throw new RuntimeException(srcFile.getPath() + "所指文件不存在");

        }

        // 开始解压

        ZipFile zipFile = null;

        try {

            zipFile = new ZipFile(srcFile, Charset.forName("gbk"));

            Enumeration<?> entries = zipFile.entries();

            while (entries.hasMoreElements()) {

                ZipEntry entry = (ZipEntry) entries.nextElement();


//                log.info("解压: " + entry.getName());

                // 如果是文件夹，就创建个文件夹

                if (entry.isDirectory()) {

                    String dirPath = destDirPath + "/" + entry.getName();

                    File dir = new File(dirPath);

                    dir.mkdirs();

                } else {

                    // 如果是文件，就先创建一个文件，然后用io流把内容copy过去

                    File targetFile = new File(destDirPath + "/" + entry.getName());

                    // 保证这个文件的父文件夹必须要存在

                    if(!targetFile.getParentFile().exists()){

                        targetFile.getParentFile().mkdirs();

                    }

                    targetFile.createNewFile();

                    // 将压缩文件内容写入到这个文件中

                    InputStream is = zipFile.getInputStream(entry);

                    FileOutputStream fos = new FileOutputStream(targetFile);

                    int len;

                    byte[] buf = new byte[1024];

                    while ((len = is.read(buf)) != -1) {

                        fos.write(buf, 0, len);

                    }

                    // 关流顺序，先打开的后关闭

                    fos.close();

                    is.close();

                }

            }

            long end = System.currentTimeMillis();

            log.info("解压完成，耗时：" + (end - start) +" ms");

        } catch (Exception e) {

            throw new RuntimeException("unzip error from ZipUtils", e);

        } finally {

            if(zipFile != null){

                try {

                    zipFile.close();

                } catch (IOException e) {

                    e.printStackTrace();

                }

            }

        }
        return true;
    }

    /**
     * 读取json 文件, Linux版
     */
    public static String readJsonLinux(String path){
        String param = FileUtils.readFile(path);
        return param;

    }



    public static void main(String[] args) {

//        unzip("F:\\test\\a1_shp2.zip", "F:\\test\\");

        // 这个是可以的，没有目录结构
//        unzip("F:\\test\\cesium\\clip.zip", "F:\\test\\cesium\\");

        // 这个有目录的，会失败
//        File file = new File("F:\\test\\clip.zip");
        unzip("F:\\test\\clip.zip", "F:\\test\\");

    }
}
