package com.apobates.forum.utils.zxing;

import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Hashtable;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.client.j2se.MatrixToImageWriter;
/**
 * 二维码的主类,有别于com.google.zxing.qrcode.encoder.QRCode
 * https://www.jianshu.com/p/6607e69b1121
 * https://www.jianshu.com/p/38c4781c1f5d
 * @author xiaofanku
 * @since 20200326
 */
public class GeneralQRCode {
	private final int width;
	private final int height;
	private final ImageType image;
	private final String content;
	
	private GeneralQRCode(String content, int width, int height, ImageType image) {
		this.content = content;
		this.width = width;
		this.height = height;
		this.image = image;
	}

	public int getWidth() {
		return width;
	}

	public int getHeight() {
		return height;
	}

	public ImageType getImage() {
		return image;
	}
	
	public String getContent() {
		return content;
	}
	
	//https://github.com/kenglxn/QRGen/blob/master/javase/src/main/java/net/glxn/qrgen/javase/QRCode.java
	/**
	 * 写入到输出文件中
	 * 
	 * @param outputFile       输出文件
	 * @throws WriterException 
	 * @throws IOException     
	 */
	public void toFile(File outputFile) throws WriterException, IOException{
		Hashtable<EncodeHintType, Object> hints = new Hashtable<>();
		// 默认为ISO-8859-1,若字符串超ASCII可以设置为UTF-8
		// hints.put(EncodeHintType.CHARACTER_SET, "UTF-8"); 
		hints.put(EncodeHintType.MARGIN, "1"); //默认为4
		// 1-39级,默认为Encoder.recommendVersion
		// hints.put(EncodeHintType.QR_VERSION, "10"); 
		// 指定生成的数据矩阵的形状(无效果)
		// hints.put(EncodeHintType.DATA_MATRIX_SHAPE, SymbolShapeHint.FORCE_SQUARE);
		// 指定纠错等级(默认:ErrorCorrectionLevel.L)纠正率越高，扫描速度越慢
		// hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L); 
		
		BitMatrix bitMatrix = new QRCodeWriter().encode(getContent(), BarcodeFormat.QR_CODE, getWidth(), getHeight(), hints);
		MatrixToImageWriter.writeToPath(bitMatrix, getImage().type, outputFile.toPath());
	}
	
	//https://github.com/zxing/zxing/blob/master/javase/src/main/java/com/google/zxing/client/j2se/MatrixToImageWriter.java
	/**
	 * 写入到输出流中
	 * 
	 * @param stream           输出流
	 * @throws IOException     
	 * @throws WriterException 
	 */
	public void toStream(OutputStream stream) throws IOException, WriterException{
		Hashtable<EncodeHintType, String> hints = new Hashtable<>();
		hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
		hints.put(EncodeHintType.MARGIN, "1");
		
		BitMatrix bitMatrix = new QRCodeWriter().encode(getContent(), BarcodeFormat.QR_CODE, getWidth(), getHeight(), hints);
		MatrixToImageWriter.writeToStream(bitMatrix, getImage().type, stream);
	}
	/**
	 * 二维码主类的构造者类
	 * 
	 * @author xiaofanku
	 * @since 20200326
	 */
	public static class GeneralQRCodeBuilder{
		private int width=128;
		private int height=128;
		private ImageType type=ImageType.PNG;
		private final String content;
		
		public GeneralQRCodeBuilder(String content) {
			super();
			this.content = content;
		}
		
		public GeneralQRCodeBuilder withSize(int width, int height){
			this.width = width;
			this.height = height;
			return this;
		}
		
		public GeneralQRCodeBuilder formatImage(ImageType type){
			this.type = type;
			return this;
		}
		
		public GeneralQRCode build(){
			return new GeneralQRCode(content, width, height, type);
		}
	}
	/**
	 * 二维码输出的图片类型,支持gif,png,jpeg
	 * 
	 * @author xiaofanku
	 * @since 20200326
	 */
	public static enum ImageType{
		GIF("gif"), PNG("png"), JPEG("jpeg");
		private final String type;

		private ImageType(String type) {
			this.type = type;
		}

		public String getType() {
			return type;
		}
		
	}
}
