// 整改自 https://github.com/davidshimjs/qrcodejs
import QRErrorCorrectLevel from "./QRErrorCorrectLevel.js";
import QRCodeLimitLength from "./QRCodeLimitLength.js";
import QRCodeModel from "./QRCodeModel.js";
export default class QRCode {
	_htOption = {
		x: 0,
		y: 0,
		width: 256,
		height: 256,
		typeNumber: 4,
		colorDark: "#000000",
		colorLight: "#ffffff",
		correctLevel: QRErrorCorrectLevel.M
	};
	_oQRCode = null;
	_context = null;
	constructor(context, vOption) {
		if (typeof vOption === 'string') {
			vOption = {
				text: vOption
			};
		}
		if (vOption) {
			for (var i in vOption) {
				this._htOption[i] = vOption[i];
			}
		}
		this._context = context
	}

	async makeCode(sText) {
		this._oQRCode = new QRCodeModel(this._getTypeNumber(sText, this._htOption.correctLevel), this._htOption
			.correctLevel);
		this._oQRCode.addData(sText);
		this._oQRCode.make();
		return await this.makeImage(true);
	}

	async calcCode(sText) {
		this._oQRCode = new QRCodeModel(this._getTypeNumber(sText, this._htOption.correctLevel), this._htOption
			.correctLevel);
		this._oQRCode.addData(sText);
		this._oQRCode.make();
		return await this.makeImage(false);
	}
	/**
	 * Get the type by string length
	 * 
	 * @private
	 * @param {String} sText
	 * @param {Number} nCorrectLevel
	 * @return {Number} type
	 */
	_getTypeNumber(sText, nCorrectLevel) {
		var nType = 1;
		var length = QRCode._getUTF8Length(sText);

		for (var i = 0, len = QRCodeLimitLength.length; i <= len; i++) {
			var nLimit = 0;

			switch (nCorrectLevel) {
				case QRErrorCorrectLevel.L:
					nLimit = QRCodeLimitLength[i][0];
					break;
				case QRErrorCorrectLevel.M:
					nLimit = QRCodeLimitLength[i][1];
					break;
				case QRErrorCorrectLevel.Q:
					nLimit = QRCodeLimitLength[i][2];
					break;
				case QRErrorCorrectLevel.H:
					nLimit = QRCodeLimitLength[i][3];
					break;
			}

			if (length <= nLimit) {
				break;
			} else {
				nType++;
			}
		}

		if (nType > QRCodeLimitLength.length) {
			throw new Error("Too long data");
		}

		return nType;
	}

	static _getUTF8Length(sText) {
		var replacedText = encodeURI(sText).toString().replace(/\%[0-9a-fA-F]{2}/g, 'a');
		return replacedText.length + (replacedText.length != sText ? 3 : 0);
	}

	async makeImage(needDraw) {
		var _oContext = this._context
		var _htOption = this._htOption;
		var oQRCode = this._oQRCode
		var padding = 0;
		if (_htOption.padding)
			padding = _htOption.padding;

		var nCount = oQRCode.getModuleCount();
		var nWidth = Math.floor((_htOption.width - 2 * padding) / nCount);
		var nHeight = Math.floor((_htOption.height - 2 * padding) / nCount);
		if (needDraw) {
			let list = [];
			for (var row = 0; row < nCount; row++) {
				for (var col = 0; col < nCount; col++) {
					var nLeft = col * nWidth + padding + _htOption.x;
					var nTop = row * nHeight + padding + _htOption.y;
					list.push({
						fillStyle: oQRCode.isDark(row, col) ? _htOption.colorDark : _htOption.colorLight,
						x: nLeft,
						y: nTop,
						w: nWidth,
						h: nHeight
					});
				}
			}
			await _oContext.fillRectList(list);
		}
		return {
			width: nWidth * nCount + 2 * padding,
			height: nHeight * nCount + 2 * padding
		}
	}
}
