package org.springblade.modules.QRCode.utils;

import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.oned.Code128Writer;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import lombok.extern.slf4j.Slf4j;
import sun.misc.BASE64Encoder;


import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.HashMap;
import java.util.Map;

/**
 * @author: lianghanqiang
 * @description: 二维码工具类
 * @since: 7/27/21 -- 1:57 PM
 */
@Slf4j
public class CodeUtils {

	private static final String PRE_FIX = "data:image/png;base64,";

	/**
	 * 	生成二维码
	 * @param logoUrl logo图片路径
	 * @param content 二维码内容
	 * */
	public static String createCode(String logoUrl,String content){
		// 二维码大小
		int width = 500, height = 500;
		// 二维码参数
		CodeStyle style = new CodeStyle();
		style.setWidth(width);
		style.setHeight(height);

		Map<EncodeHintType, Object> hints = new HashMap<>();
		//内容编码格式
		hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
		// 指定纠错等级
		hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
		//设置二维码边的空度，非负数
		hints.put(EncodeHintType.MARGIN, 1);

		// 生成二维码图片
		QRCodeWriter writer = new QRCodeWriter();
		BitMatrix bm = null;

		try {
			bm = writer.encode(content, BarcodeFormat.QR_CODE, style.getWidth(), style.getHeight(), hints);
		} catch (WriterException e) {
			log.error("二维码生成异常："+e.getMessage());
		}

		int margin = style.getMargin();
		int tempM = margin*2;
		int[] rec = bm.getEnclosingRectangle();   //获取二维码图案的属性
		int resWidth = rec[2] + tempM;
		int resHeight = rec[3] + tempM;
		BitMatrix resMatrix = new BitMatrix(resWidth, resHeight); // 按照自定义边框生成新的BitMatrix
		resMatrix.clear();
		for (int i = margin; i < resWidth - margin; i++) {   //循环，将二维码图案绘制到新的bitMatrix中
			for (int j = margin; j < resHeight - margin; j++){
				if (bm.get(i - margin + rec[0], j - margin + rec[1])){
					resMatrix.set(i, j);
				}
			}
		}
		bm = resMatrix;

		int w = bm.getWidth();
		int h = bm.getHeight();
		BufferedImage qrcodeBuffImg = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);

		// 开始利用二维码数据创建Bitmap图片
		for (int x = 0; x < w; x++) {
			for (int y = 0; y < h; y++) {
				qrcodeBuffImg.setRGB(x, y, bm.get(x, y) ? style.getCodeColor() : style.getBackgroundColor());
			}
		}

		/**
		 * 读取Logo图片
		 */
		if(logoUrl!=null){
			BufferedImage logo = null;
			try {
				logo = ImageIO.read(new ByteArrayInputStream(HttpUtil.downloadBytes(logoUrl)));
			} catch (IOException e) {
				log.error("logo文件读取失败"+e.getMessage());
			}

			/**
			 * 设置logo的大小，设置为二维码图片的20%
			 */
			int widthLogo = logo.getWidth(null) > qrcodeBuffImg.getWidth() * 3 / 10 ? (qrcodeBuffImg.getWidth() * 3 / 10)
				: logo.getWidth(null),
				heightLogo = logo.getHeight(null) > qrcodeBuffImg.getHeight() * 3 / 10 ? (qrcodeBuffImg.getHeight() * 3 / 10) : logo.getWidth(null);

			/**
			 * logo在二维码的位置
			 */
			int x = (qrcodeBuffImg.getWidth() - widthLogo) / 2;
			int y = (qrcodeBuffImg.getHeight() - heightLogo) / 2;

			Graphics2D qrcodeOutg = qrcodeBuffImg.createGraphics();
			// 把logo写到二维码图片中间
			qrcodeOutg.drawImage(logo, x, y, widthLogo, heightLogo, null);
			qrcodeOutg.dispose();
			qrcodeBuffImg.flush();
		}

		return toBase64(qrcodeBuffImg);
	}


	/**
	 * 	生成条形码
	 * @param content 条形码内容
	 * */
	public static String createBar(String content){
		BitMatrix bitMatrix = new Code128Writer().encode(content, BarcodeFormat.CODE_128, 300, 80, null);
		BufferedImage bufferedImage = MatrixToImageWriter.toBufferedImage(bitMatrix);
		return toBase64(bufferedImage);
	}

	private static String toBase64(BufferedImage qrcodeBuffImg){
		ByteArrayOutputStream baos = new ByteArrayOutputStream();//io流
		try {
			ImageIO.write(qrcodeBuffImg, "png", baos);//写入流中
		} catch (IOException e) {
			log.error("二维码生成异常："+e.getMessage());
		}
		byte[] bytes = baos.toByteArray();//转换成字节
		BASE64Encoder encoder = new BASE64Encoder();
		String png_base64 =  encoder.encodeBuffer(bytes).trim();//转换成base64串
		png_base64 = png_base64.replaceAll("\n", "").replaceAll("\r", "");
		return PRE_FIX+png_base64;
	}

	public static void main(String[] args) {
		String sdf = createCode(null, "sdf");
		System.out.println(sdf);
	}
}
