package com.yeejoin.amos.boot.module.app.biz.utils;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.common.BitMatrix;
import com.itextpdf.text.pdf.qrcode.ErrorCorrectionLevel;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class ImageUtils {

    private static final int QRCOLOR = 0x201f1f; // 二维码颜色:黑色
    private static final int BGWHITE = 0xFFFFFF; //二维码背景颜色:白色
    private static Map<EncodeHintType, Object> hints = new HashMap<EncodeHintType, Object>() {
        private static final long serialVersionUID = 1L;

        {
            put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);// 设置QR二维码的纠错级别(H为最高级别)
            put(EncodeHintType.CHARACTER_SET, "utf-8");// 设置编码方式
            put(EncodeHintType.MARGIN, 0);// 白边
        }
    };

    /**
     * 生成二维码图片+背景+文字描述
     *
     * @param codeFile  生成图地址
     * @param bgImgFile 背景图地址
     * @param width     二维码宽度
     * @param height    二维码高度
     * @param qrUrl     内容
     * @param note      文字说明
     * @param tui       文字说明2
     * @param size      文字大小
     * @param imagesX   二维码x轴方向
     * @param imagesY   二维码y轴方向
     * @param text1X    文字描述1x轴方向
     * @param text1Y    文字描述1y轴方向
     * @param text2X    文字描述2x轴方向
     * @param text2Y    文字描述2y轴方向
     */
    public static void creatQRCode(File codeFile, InputStream bgImgFile, Integer width, Integer height, String qrUrl,
                                   String note, String tui, Integer size, Integer imagesX, Integer imagesY, Integer text1X, Integer text1Y
            , Integer text2X, Integer text2Y) throws IOException {
        try {
            MultiFormatWriter multiFormatWriter = new MultiFormatWriter();
            BitMatrix bm = multiFormatWriter.encode(qrUrl, BarcodeFormat.QR_CODE, width, height, hints);
            BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
            for (int x = 0; x < width; x++) {
                for (int y = 0; y < height; y++) {
                    image.setRGB(x, y, bm.get(x, y) ? QRCOLOR : BGWHITE);
                }
            }
            BufferedImage backgroundImage = ImageIO.read(bgImgFile);
            int bgWidth = backgroundImage.getWidth();
            int qrWidth = image.getWidth();
            int disx = (bgWidth - qrWidth) - imagesX;
            int disy = imagesY;
            Graphics2D rng = backgroundImage.createGraphics();
            rng.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP));
            rng.drawImage(image, disx, disy, width, height, null);
            // 抗锯齿
            rng.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            // 文字描述参数设置
            Color textColor = Color.white;
            rng.setColor(textColor);
            rng.drawImage(backgroundImage, 0, 0, null);
            // 设置字体类型和大小(BOLD加粗/ PLAIN平常)
            rng.setFont(new Font("Microsoft YaHei", Font.BOLD, size));
            // 设置字体颜色
            rng.setColor(Color.black);
            int strWidth = rng.getFontMetrics().stringWidth(note);
            // 文字1显示位置
            int disx1 = (bgWidth - strWidth) - text1X;//左右
            rng.drawString(note, disx1, text1Y);//上下
            // 文字2显示位置
            int disx2 = (bgWidth - strWidth) - text2X;//左右
            rng.drawString(tui, disx2, text2Y);//上下
            rng.dispose();
            image = backgroundImage;
            image.flush();
            ImageIO.write(image, "png", codeFile);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (null != bgImgFile) {
                bgImgFile.close();
            }
        }
    }


    /**
     * 下载图片
     *
     * @param fileName
     * @param resourceName
     * @param response
     */
    public static void downloadResource(String fileName, String resourceName, HttpServletResponse response) {
        DataInputStream in = null;
        OutputStream out = null;
        InputStream fileInputStream = null;
        try {
            response.reset();
            response.setCharacterEncoding("UTF-8");
            response.setHeader("content-Type", "image/png");
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
            response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
            fileInputStream = new FileInputStream(resourceName);
            in = new DataInputStream(fileInputStream);
            out = response.getOutputStream();
            int bytes = 0;
            byte[] bufferOut = new byte[1024];
            while ((bytes = in.read(bufferOut)) != -1) {
                out.write(bufferOut, 0, bytes);
            }
        } catch (Exception e) {
            e.printStackTrace();
            response.reset();
        } finally {
            try {
                if (out != null) {
                    out.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (in != null) {
                    in.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (fileInputStream != null) {
                    fileInputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }


    }

    /**
     * 下载压缩包
     *
     * @param fileName
     * @param resourceName
     * @param response
     */
    public static void downloadResourceZip(String fileName, String resourceName, HttpServletResponse response) {
        DataInputStream in = null;
        OutputStream out = null;
        InputStream fileInputStream = null;
        try {
            response.reset();
            response.setCharacterEncoding("UTF-8");
            response.setHeader("content-Type", "application/zip");
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
            response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
            fileInputStream = new FileInputStream(resourceName);
            in = new DataInputStream(fileInputStream);
            out = response.getOutputStream();
            int bytes = 0;
            byte[] bufferOut = new byte[1024];
            while ((bytes = in.read(bufferOut)) != -1) {
                out.write(bufferOut, 0, bytes);
            }
        } catch (Exception e) {
            e.printStackTrace();
            response.reset();
        } finally {
            try {
                if (out != null) {
                    out.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (in != null) {
                    in.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (fileInputStream != null) {
                    fileInputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }


    /**
     * 压缩文件
     *
     * @param srcFiles
     * @param zipFile
     */
    public static void zipFiles(List<File> srcFiles, File zipFile) {
        try {
            if (srcFiles.size() != 0) {
                // 判断压缩后的文件存在不，不存在则创建
                if (!zipFile.exists()) {
                    zipFile.createNewFile();
                } else {
                    zipFile.delete();
                    zipFile.createNewFile();
                }
                // 创建 FileInputStream 对象
                InputStream fileInputStream = null;
                // 实例化 FileOutputStream 对象
                FileOutputStream fileOutputStream = new FileOutputStream(zipFile);
                // 实例化 ZipOutputStream 对象
                ZipOutputStream zipOutputStream = new ZipOutputStream(fileOutputStream);
                // 创建 ZipEntry 对象
                ZipEntry zipEntry = null;
                // 遍历源文件数组
//                for (int i = 0; i < srcFiles.size(); i++) {
//                    // 将源文件数组中的当前文件读入 FileInputStream 流中
//                    File file = srcFiles.get(i);
//                    fileInputStream = new FileInputStream(file);
//                    // 实例化 ZipEntry 对象，源文件数组中的当前文件
//                    zipEntry = new ZipEntry(i + ".jpg");
//                    zipOutputStream.putNextEntry(zipEntry);
//                    // 该变量记录每次真正读的字节个数
//                    int len;
//                    // 定义每次读取的字节数组
//                    byte[] buffer = new byte[1024];
//                    while ((len = fileInputStream.read(buffer)) > 0) {
//                        zipOutputStream.write(buffer, 0, len);
//                    }
//                }
                for (File srcFile : srcFiles) {
                    fileInputStream = new FileInputStream(srcFile);
                    // 实例化 ZipEntry 对象，源文件数组中的当前文件
                    zipEntry = new ZipEntry(srcFile.getName());
                    zipOutputStream.putNextEntry(zipEntry);
                    // 该变量记录每次真正读的字节个数
                    int len;
                    // 定义每次读取的字节数组
                    byte[] buffer = new byte[1024];
                    while ((len = fileInputStream.read(buffer)) > 0) {
                        zipOutputStream.write(buffer, 0, len);
                    }
                }
                zipOutputStream.closeEntry();
                zipOutputStream.close();
                fileInputStream.close();
                fileOutputStream.close();
                System.out.println("下载完成");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 删除文件夹（强制删除）
     *
     * @param file
     */
    public static void deleteAllFilesOfDir(File file) {
        if (null != file) {
            if (!file.exists())
                return;
            if (file.isFile()) {
                boolean result = file.delete();
                int tryCount = 0;
                while (!result && tryCount++ < 10) {
                    System.gc(); // 回收资源
                    result = file.delete();
                }
            }
            File[] files = file.listFiles();
            if (null != files) {
                for (int i = 0; i < files.length; i++) {
                    deleteAllFilesOfDir(files[i]);
                }
            }
            file.delete();
        }

    }
}
