package com.chushang.common.core.util;

import cn.hutool.core.io.FileUtil;
import lombok.SneakyThrows;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class FileUtils extends FileUtil {
    private static final Logger log = LoggerFactory.getLogger(FileUtils.class);

    @SneakyThrows
    public static void createFile(InputStream inputStream, String filename) {
        File tmp = new File(filename);
        OutputStream os = Files.newOutputStream(tmp.toPath());
        try (inputStream) {
            int bytesRead;
            byte[] buffer = new byte[8192];
            while ((bytesRead = inputStream.read(buffer, 0, 8192)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
        }
    }

    private static final char[] Digit = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};

    public static void writeBytes(String filePath, OutputStream os) throws IOException {
        FileInputStream fis = null;

        try {
            File file = new File(filePath);
            if (!file.exists()) {
                throw new FileNotFoundException(filePath);
            }

            fis = new FileInputStream(file);
            byte[] b = new byte[1024];

            int length;
            while ((length = fis.read(b)) > 0) {
                os.write(b, 0, length);
            }
        } catch (IOException var9) {
            IOException e = var9;
            throw e;
        } finally {
            if (os != null) {
                os.close();
            }

            if (fis != null) {
                fis.close();
            }

        }

    }

    public static boolean deleteFile(String filePath) {
        boolean flag = false;
        File file = new File(filePath);
        if (file.isFile() && file.exists()) {
            file.delete();
            flag = true;
        }

        return flag;
    }

    public static String setFileDownloadHeader(HttpServletRequest request, String fileName) throws UnsupportedEncodingException {
        String agent = request.getHeader("USER-AGENT");
        String filename = fileName;
        if (agent.contains("MSIE")) {
            filename = URLEncoder.encode(filename, StandardCharsets.UTF_8);
            filename = filename.replace("+", " ");
        } else if (agent.contains("Firefox")) {
            filename = new String(fileName.getBytes(), "ISO8859-1");
        } else if (agent.contains("Chrome")) {
            filename = URLEncoder.encode(filename, StandardCharsets.UTF_8);
        } else {
            filename = URLEncoder.encode(filename, StandardCharsets.UTF_8);
        }

        return filename;
    }

    public static void setAttachmentResponseHeader(HttpServletResponse response, String realFileName) throws UnsupportedEncodingException {
        String percentEncodedFileName = percentEncode(realFileName);
        response.setHeader("Content-disposition", "attachment; filename=" + percentEncodedFileName + ";" + "filename*=" + "utf-8''" + percentEncodedFileName);
    }

    public static String percentEncode(String s) throws UnsupportedEncodingException {
        String encode = URLEncoder.encode(s, StandardCharsets.UTF_8);
        return encode.replaceAll("\\+", "%20");
    }

    public static String getFileExtendName(byte[] photoByte) {
        String strFileExtendName = "jpg";
        if (photoByte[0] == 71 && photoByte[1] == 73 && photoByte[2] == 70 && photoByte[3] == 56 && (photoByte[4] == 55 || photoByte[4] == 57) && photoByte[5] == 97) {
            strFileExtendName = "gif";
        } else if (photoByte[6] == 74 && photoByte[7] == 70 && photoByte[8] == 73 && photoByte[9] == 70) {
            strFileExtendName = "jpg";
        } else if (photoByte[0] == 66 && photoByte[1] == 77) {
            strFileExtendName = "bmp";
        } else if (photoByte[1] == 80 && photoByte[2] == 78 && photoByte[3] == 71) {
            strFileExtendName = "png";
        }

        return strFileExtendName;
    }

    public static String getName(String fileName) {
        if (fileName == null) {
            return null;
        } else {
            int lastUnixPos = fileName.lastIndexOf(47);
            int lastWindowsPos = fileName.lastIndexOf(92);
            int index = Math.max(lastUnixPos, lastWindowsPos);
            return fileName.substring(index + 1);
        }
    }

    public static String getNameNotSuffix(String fileName) {
        String baseName = getName(fileName);
        if (baseName != null && !baseName.trim().isEmpty()) {
            int index = baseName.lastIndexOf(".");
            return baseName.substring(0, index);
        } else {
            return null;
        }
    }

    public static String getExtension(String fileName) {
        String baseName = getName(fileName);
        if (baseName != null && !baseName.trim().isEmpty()) {
            int index = baseName.lastIndexOf(".");
            return baseName.substring(index + 1);
        } else {
            return null;
        }
    }

    public static String getMd5(File f) {
        try (FileInputStream fis = new FileInputStream(f)){
            return getMd5(fis);
        }catch (Exception e){
            e.printStackTrace();
        }
        return "";
    }

    public static String getMd5(InputStream is) throws IOException, NoSuchAlgorithmException {
        MessageDigest mdInst = MessageDigest.getInstance("MD5");
        byte[] buffer = new byte[1024];
        while (is.read(buffer) != -1) {
            mdInst.update(buffer);
        }
        return binaryToHexString(mdInst.digest());
    }

    private static String binaryToHexString(byte[] result) {
        StringBuilder digestHexStr = new StringBuilder();

        for (int i = 0; i < 16; ++i) {
            char[] ob = new char[]{Digit[result[i] >>> 4 & 15], Digit[result[i] & 15]};
            String s = new String(ob);
            digestHexStr.append(s);
        }

        return digestHexStr.toString();
    }

    public static boolean isText(File file) {
        boolean isText = true;
        try (FileInputStream fin = new FileInputStream(file)){
            long len = file.length();
            for (int j = 0; j < (int) len; ++j) {
                int t = fin.read();
                if (t < 32 && t != 9 && t != 10 && t != 13) {
                    isText = false;
                    break;
                }
            }
        }catch (Exception e){
            log.error("isText", e);
        }
        return isText;
    }

    public static String getFileCharset(File sourceFile) {
        String charset = "GBK";
        byte[] first3Bytes = new byte[3];
        String var7;
        try (FileInputStream fis = new FileInputStream(sourceFile);
             BufferedInputStream bis = new BufferedInputStream(fis)){
            boolean checked = false;
            bis.mark(0);
            int read = bis.read(first3Bytes, 0, 3);
            if (read != -1) {
                if (first3Bytes[0] == -1 && first3Bytes[1] == -2) {
                    charset = "UTF-16LE";
                    checked = true;
                } else if (first3Bytes[0] == -2 && first3Bytes[1] == -1) {
                    charset = "UTF-16BE";
                    checked = true;
                } else if (first3Bytes[0] == -17 && first3Bytes[1] == -69 && first3Bytes[2] == -65) {
                    charset = "UTF-8";
                    checked = true;
                }
                bis.reset();
                if (!checked) {
                    label248:
                    do {
                        do {
                            if ((read = bis.read()) == -1 || read >= 240 || 128 <= read && read <= 191) {
                                break label248;
                            }

                            if (192 <= read && read <= 223) {
                                read = bis.read();
                                continue label248;
                            }
                        } while(224 > read || read > 239);

                        read = bis.read();
                        if (128 <= read && read <= 191) {
                            read = bis.read();
                            if (128 <= read && read <= 191) {
                                charset = "UTF-8";
                            }
                        }
                        break;
                    } while(128 <= read && read <= 191);
                }

                bis.close();
                return charset;
            }

            var7 = charset;
        } catch (Exception e) {
            e.printStackTrace();
            return charset;
        }
        return var7;
    }

}
