package com.mvc.utils;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class FileUtil {

    /**
     * 获取目录下文件名称列表
     */
    public static List<String> getFilenameList(String path) {
        List<String> filenameList = new ArrayList<>();
        File dir = new File(path);
        if (!dir.isDirectory()) {
            return filenameList;
        }

        File[] files = dir.listFiles();
        if (files != null) {
            for (File file : files) {
                filenameList.add(file.getName());
            }
        }

        return filenameList;
    }

    /**
     * 写入文件
     *
     * @param dir
     * @param filename
     * @param data
     */
    public static void writeBytesFile(String dir, String filename, byte[] data) throws IOException {
        File directory = new File(dir);
        if (!directory.exists()) {
            directory.mkdirs();
        }

        FileOutputStream fos = new FileOutputStream(dir + filename);
        fos.write(data);
        fos.close();
    }

    /**
     * 读取文件
     *
     * @param dir
     * @param filename
     * @return
     * @throws IOException
     */
    public static byte[] readBytesFile(String dir, String filename) throws IOException {
        FileInputStream fis = new FileInputStream(new File(dir + filename));
        byte[] buffer = fis.readAllBytes();
        fis.close();
        return buffer;
    }

    /**
     * 写入文件
     *
     * @param dir
     * @param filename
     * @param data
     */
    public static void writeCharsFile(String dir, String filename, char[] data) throws IOException {
        File directory = new File(dir);
        if (!directory.exists()) {
            directory.mkdirs();
        }

        BufferedWriter bw = new BufferedWriter(new FileWriter(dir + filename));
        bw.write(data);
        bw.close();
    }

    /**
     * 线上图片转为byte数组
     *
     * @param path
     * @return
     */
    public static byte[] onlineImage2byte(String path) throws IOException {
        byte[] data = null;
        URL url = null;
        InputStream input = null;
        try {
            url = new URL(path);
            HttpURLConnection httpUrl = (HttpURLConnection) url.openConnection();

            httpUrl.setConnectTimeout(2000);
            httpUrl.setReadTimeout(2000);

            httpUrl.connect();
            httpUrl.getInputStream();
            input = httpUrl.getInputStream();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        byte[] buf = new byte[1024];
        int numBytesRead = 0;
        while ((numBytesRead = input.read(buf)) != -1) {
            output.write(buf, 0, numBytesRead);
        }
        data = output.toByteArray();
        output.close();
        input.close();
        return data;
    }

    /**
     * 读取文件
     *
     * @param filename
     * @return
     * @throws IOException
     */
    public static byte[] readBytesFile(String filename) throws IOException {
        File file = new File(filename);
        if (!file.exists() || !file.isFile()) return null;
        FileInputStream fis = new FileInputStream(file);
        byte[] buffer = fis.readAllBytes();
        fis.close();
        return buffer;
    }

    /**
     * bmp转Jpg
     *
     * @param filePath
     * @param outPath
     * @return
     */
    public static String bmp2Jpeg(String filePath, String outPath) {
        try {
            File file = new File(filePath);
            BufferedImage tag = ImageIO.read(file);
            String formatName = outPath.substring(outPath.lastIndexOf(".") + 1);
            ImageIO.write(tag, formatName, new File(outPath));
            return outPath;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return outPath;
    }

    /**
     * 文件下载到指定路径
     *
     * @param urlString 链接
     * @param savePath  保存路径
     * @param filename  文件名
     * @throws Exception
     */
    public static void download(String urlString, String savePath, String filename) throws IOException {
        // 构造URL
        URL url = new URL(urlString);
        // 打开连接
        URLConnection con = url.openConnection();
        //设置请求超时为20s
        con.setConnectTimeout(20 * 1000);
        //文件路径不存在 则创建
        File sf = new File(savePath);
        if (!sf.exists()) {
            sf.mkdirs();
        }
        //jdk 1.7 新特性自动关闭
        try (InputStream in = con.getInputStream();
             OutputStream out = new FileOutputStream(sf.getPath() + "\\" + filename)) {
            //创建缓冲区
            byte[] buff = new byte[1024];
            int n;
            // 开始读取
            while ((n = in.read(buff)) >= 0) {
                out.write(buff, 0, n);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取文件SHA256校验码
     *
     * @param filePath
     * @return
     * @throws IOException
     * @throws NoSuchAlgorithmException
     */
    public static String getFileSHA256Hash(String filePath) throws IOException, NoSuchAlgorithmException {
        MessageDigest md = MessageDigest.getInstance("SHA-256");

        try (FileInputStream fis = new FileInputStream(filePath)) {
            byte[] buffer = new byte[4096];
            int read;

            while ((read = fis.read(buffer)) != -1) {
                md.update(buffer, 0, read);
            }

            byte[] hashBytes = md.digest();
            StringBuilder sb = new StringBuilder();

            for (byte b : hashBytes) {
                sb.append(String.format("%02x", b));
            }

            return sb.toString();
        }
    }

    /**
     * 获取文件MD5校验码
     *
     * @param filePath
     * @return
     * @throws IOException
     * @throws NoSuchAlgorithmException
     */
    public static String getFileMD5(String filePath) throws IOException, NoSuchAlgorithmException {
        MessageDigest md = MessageDigest.getInstance("MD5");

        try (FileInputStream fis = new FileInputStream(filePath);
             DigestInputStream dis = new DigestInputStream(fis, md)) {

            // 读取文件直到结束，这样所有数据都会经过MessageDigest进行处理
            while (dis.read() != -1) {
                // 实际上这里可以按需调整缓冲区大小，每次读取一定字节数的数据
            }

            byte[] digest = md.digest();

            StringBuilder sb = new StringBuilder();
            for (byte b : digest) {
                sb.append(String.format("%02x", b));
            }

            return sb.toString();
        }
    }

    /**
     * 获取文件名扩展名
     *
     * @param fileName
     * @return 含.
     */
    public static String getFileExtension(String fileName) {
        int lastDotIndex = fileName.lastIndexOf(".");
        if (lastDotIndex == -1) {
            return ""; // 如果没有点，则表示没有扩展名
        }
        return fileName.substring(lastDotIndex);
    }

    /**
     * 压缩文件
     *
     * @param srcFiles
     * @return
     */
    public static byte[] zipFile(List<String> srcFiles) {
        try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
             ZipOutputStream zos = new ZipOutputStream(baos)) {

            for (String fileName : srcFiles) {
                File fileToZip = new File(fileName);
                if (!fileToZip.exists()) {
                    continue;
                }
                FileInputStream fis = new FileInputStream(fileToZip);
                ZipEntry zipEntry = new ZipEntry(fileToZip.getName());
                zos.putNextEntry(zipEntry);

                byte[] bytes = new byte[1024];
                int length;
                while ((length = fis.read(bytes)) >= 0) {
                    zos.write(bytes, 0, length);
                }

                zos.closeEntry();
                fis.close();
            }
            zos.finish();
            zos.close();
            return baos.toByteArray();

        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 文件大小转换(字节转为KB、MB...)
     * @param bytes
     * @return
     */
    public static String convertFileSize(long bytes) {
        if (bytes < 1024) {
            return bytes + " B";
        }
        int exp = (int) (Math.log(bytes) / Math.log(1024));
        String[] units = new String[]{"KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"};
        double value = bytes / Math.pow(1024, exp);
        return String.format("%.2f %s", value, units[exp - 1]);
    }

    public static void main(String[] args) throws IOException, NoSuchAlgorithmException {

    }
}
