package com.xinelu.common.utils;

import cn.hutool.core.io.FileUtil;
import cn.hutool.extra.qrcode.BufferedImageLuminanceSource;
import cn.hutool.extra.qrcode.QrCodeUtil;
import cn.hutool.extra.qrcode.QrConfig;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.DecodeHintType;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.Result;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import com.xinelu.common.utils.uuid.IdUtils;
import java.awt.BasicStroke;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Shape;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Hashtable;
import java.util.concurrent.atomic.AtomicInteger;
import javax.imageio.ImageIO;
import org.apache.commons.lang3.StringUtils;

/**
 * 二维码生成类
 *
 * @author haown
 * @date 2023-01-31
 */
public class QrCodeUtils {

    private static final String CHARSET = "UTF-8";
    private static final String FORMAT = "JPG";
    // 二维码尺寸
    private static final int QRCODE_SIZE = 300;
    // LOGO宽度
    private static final int LOGO_WIDTH = 60;
    // LOGO高度
    private static final int LOGO_HEIGHT = 60;

    /**
     * 创建二维码图片
     *
     * @param content  二维码内容
     * @param width    生成二维码长度
     * @param height   生成二维码高度
     * @param filePath 二维码存放路径
     */
    public static void createEwm(String content, Integer width, Integer height, String filePath) {
        // 二维码生成
        QrConfig config = new QrConfig(width, height);
        // 设置边距，既二维码和背景之间的边距
        config.setMargin(0);
        QrCodeUtil.generate(content, config, FileUtil.file(filePath));
    }

    /**
     * @return java.lang.Boolean
     * @Author mengkuiliang
     * @Description 生成二维码
     * @Date 2023-01-04 19:58
     * @Param [ ontent：二维码内容
     * logoPath：logo图片路径
     * savePath：二维码保存地址
     * fileName：二维码文件名
     * bCompress：是否压缩logo
     * ]
     **/
    public static Boolean generate(String content, String logoPath, String savePath, String fileName, boolean bCompress) {
        try {
            // 生成图片
            BufferedImage image = createImage(content, logoPath, bCompress);
            // 创建输出目录
            mkdirs(savePath);
            // 生成文件名    文件名为空时自动生成
            if (StringUtils.isBlank(fileName)) {
                fileName = IdUtils.fastSimpleUUID() + "." + FORMAT.toLowerCase();
            } else {
                fileName = fileName.substring(0, fileName.lastIndexOf(".") > 0 ? fileName.lastIndexOf(".") : fileName.length()) + "." + FORMAT.toLowerCase();
            }
            // 写文件
            ImageIO.write(image, FORMAT, new File(savePath + "/" + fileName));
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * @return java.lang.String
     * @Author mengkuiliang
     * @Description 解析二维码
     * @Date 2023-01-04 19:58
     * @Param [filePath：图片路径]
     **/
    public static String analysis(String filePath) throws Exception {
        if (StringUtils.isBlank(filePath)) {
            return null;
        }
        BufferedImage image;
        image = ImageIO.read(new File(filePath));
        if (image == null) {
            return null;
        }
        BufferedImageLuminanceSource source = new BufferedImageLuminanceSource(image);
        BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
        Hashtable<DecodeHintType, Object> hints = new Hashtable<DecodeHintType, Object>();
        hints.put(DecodeHintType.CHARACTER_SET, CHARSET);
        Result result = new MultiFormatReader().decode(bitmap, hints);
        return result.getText();
    }

    /**
     * 生成图片
     */
    private static BufferedImage createImage(String content, String logoPath, boolean bCompress) throws Exception {
        Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
        hints.put(EncodeHintType.CHARACTER_SET, CHARSET);
        hints.put(EncodeHintType.MARGIN, 1);
        BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, QRCODE_SIZE, QRCODE_SIZE, hints);
        int width = bitMatrix.getWidth();
        int height = bitMatrix.getHeight();
        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, bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF);
            }
        }
        // 插入logo
        if (!StringUtils.isBlank(logoPath)) {
            insertLogo(image, logoPath, bCompress);
        }
        return image;
    }

    /***
     * @Author mengkuiliang
     * @Description 插入LOGO
     * @Date 2023-01-04 19:58
     * @Param [source：源图片, logoPath：logo文件地址, bCompress：是否压缩]
     * @return void
     **/
    private static void insertLogo(BufferedImage source, String logoPath, boolean bCompress) throws Exception {
        if (!StringUtils.isBlank(logoPath)) {
            File file = new File(logoPath);
            if (file.exists()) {
                Image src = ImageIO.read(file);
                int width = src.getWidth(null);
                int height = src.getHeight(null);
                // 压缩LOGO
                if (bCompress) {
                    if (width > LOGO_WIDTH) {
                        width = LOGO_WIDTH;
                    }
                    if (height > LOGO_HEIGHT) {
                        height = LOGO_HEIGHT;
                    }
                    Image image = src.getScaledInstance(width, height, Image.SCALE_SMOOTH);
                    BufferedImage tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
                    Graphics g = tag.getGraphics();
                    g.drawImage(image, 0, 0, null); // 绘制缩小后的图
                    g.dispose();
                    src = image;
                }
                // 生成LOGO
                Graphics2D graph = source.createGraphics();
                int x = (QRCODE_SIZE - width) / 2;
                int y = (QRCODE_SIZE - height) / 2;
                graph.drawImage(src, x, y, width, height, null);
                Shape shape = new RoundRectangle2D.Float(x, y, width, width, 6, 6);
                graph.setStroke(new BasicStroke(3f));
                graph.draw(shape);
                graph.dispose();
            }
        }
    }

	public static void createTxm(String content, String filePath, String fileName) {
		// 条形码生成
		BarcodeFormat barcodeFormat = BarcodeFormat.CODE_128;
		AtomicInteger codeWidth = new AtomicInteger(3 + // start guard
			(7 * 6) + // left bars
			5 + // middle guard
			(7 * 6) + // right bars
			3); // end guard
		codeWidth.set(Math.max(codeWidth.get(), 180));
		try {
			BufferedImage txmImg = QrCodeUtil.generate(content, barcodeFormat, codeWidth.get(), 50);

			File imgFilePath = new File(filePath + fileName);
			if (!imgFilePath.exists()) {
				imgFilePath.getParentFile().mkdir();
				imgFilePath.createNewFile();
			}

			File outputfile = new File(filePath + fileName);
			ImageIO.write(txmImg, "png", outputfile);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

    /**
     * 当文件夹不存在时，自动创建多层目录
     */
    public static void mkdirs(String path) {
        File file = new File(path);
        if (!file.exists() && !file.isDirectory()) {
            file.mkdirs();
        }
    }
}
