<template>
	<view class="print-page">
		<ch-nav-bar :height="66" title="选择打印机" :rightWidth="140">
			<block v-slot:right>
				<ch-nav-btn icon="paperplane-filled" iconSize="28" color="#fff" @click="print">
					打印
				</ch-nav-btn>
				<!-- <ch-nav-btn icon="paperplane-filled" iconSize="28" color="#fff" @click="printImg">
					图片
				</ch-nav-btn> -->
			</block>
		</ch-nav-bar>
		<!-- <canvas ref="canvasRef" canvas-id="imgCanvas" id="imgCanvas" :style="`width: ${canvasW}px; height: ${canvasH}px;`"/> -->
		<uni-section title="附近打印机" type="line">
			<block v-slot:right>
				<button type="primary" size="mini" class="search-btn" :loading="searching" :disabled="searching" @click="searchDevices">{{ searching ? '搜索中...' : '搜索打印机' }}</button>
			</block>
			<uni-list>
				<block v-for="item in devices" :key="item.deviceId">
					<uni-list-item
						showArrow
						showExtraIcon
						:extraIcon="extraIcon"
						:clickable="true" 
						:title="item.name || '未知设备'" 
						@click="connectBLE(item.deviceId)">
						<block v-slot:footer>
							<text>{{ item.deviceId == connectId ? '已连接' : ''}}</text>
						</block>
					</uni-list-item>
				</block>
			</uni-list>
		</uni-section>
	</view>
</template>

<script setup>
	import { onBeforeUnmount, onMounted, reactive, toRefs, ref, nextTick } from 'vue';
	import Bluetooth from '@/components/xun-bluetoothPrint-t/print/bluetooth.js'
	import PrinterJobs from '@/components/xun-bluetoothPrint-t/print/printerjobs.js'
	import printerUtil from '@/components/xun-bluetoothPrint-t/print/printerutil.js'
import printerJobs from '@/components/xun-bluetoothPrint-t/print/printerjobs.js';
import { getImgData } from '@/api/common.js';
	 
	// #ifdef APP-PLUS
	const bluetooth = new Bluetooth();
	// #endif
	
	// const canvasRef = ref(null);
	
	const data = reactive({
		searching: false,
		connectId: '',
		printUUIDs: ["E7810A71-73AE-499D-8C15-FAA9AEF0C3F2"],
		devices: [],
		currentDevices: [],
		writeId: '',
		extraIcon: {
			type: 'smallcircle',
			color: '#4cd964',
			size: '32'
		},
		questions: [],
		canvasH: 300,
		canvasW: 150,
		imgPixData: null
	});
	
	const { devices, currentDevices, writeId, printUUIDs, searching, connectId, extraIcon, questions, canvasH, canvasW, imgPixData } = toRefs(data);
	
	onMounted(() => {
		uni.getStorage({
			key: 'questions',
			success: (res) => {
				questions.value = JSON.parse(res.data)
				console.log(questions.value)
				// getImg();
			}
		})
	})
	
	onBeforeUnmount(() => {
		// #ifdef APP-PLUS
		bluetooth.closeBluetoothAdapter() // 关闭蓝牙模块
		// #endif
	})
	
	// 搜索打印机
	function searchDevices () {
		closeConnection()
		devices.value = []
		searching.value = true;
		bluetooth.startBluetoothDevicesDiscovery({
			uuids: printUUIDs.value,
			isListen: true,
			callback: addDevices
		})
		
		setTimeout(() => {
			stopSearch()
		}, 20000)
	}
	
	// 停止搜索
	function stopSearch () {
		bluetooth.stopBluetoothDevicesDiscovery()
		searching.value = false;
	}
	
	// 添加打印机
	function addDevices (newDevices) {
		devices.value = newDevices
		console.log(devices.value)
	}
	
	// 连接打印机
	function connectBLE (id) {
		console.log(id);
		searching && stopSearch();
		bluetooth.createBLEConnection(id).then(res => {
			connectId.value = id;
			setTimeout(() => {
				bluetooth.getBLEDeviceServices().then(services => {
					return bluetooth.getBLEDeviceCharacteristics(printUUIDs.value[0])
				}).then(res => {
					res.writeId ? (writeId.value = res.writeId) 
											: uni.showToast({ title: '该打印机服务无法打印' })
				})
			}, 1000)
		})
	}
	
	// 断开连接
	function closeConnection () {
		if (!connectId) return;
		bluetooth.closeBLEConnection()
		connectId.value = ''
	}
	
	// 发送二进制数据
	function print(){
		if (!writeId.value) {
			uni.showToast({
				icon: 'none',
				title: '请连接打印机'
			})
			return;
		}
		const printerJobs = new PrinterJobs();
		
		const quesArr = questions.value.forEach(ques => {
			const quesItem = formatQuestion(ques);
			
			Object.keys(quesItem).forEach(key => {
				const item = quesItem[key];
				switch (key) {
					case 'content':
						printTitleContent(printerJobs, item.textArr);
						break;
					case 'options':
						printOption(printerJobs, item);
						break;
					case 'answer':
						printAnswerExplain(printerJobs, item.textArr, 'answer');
						break;
					case 'explain':
						printAnswerExplain(printerJobs, item.textArr, 'explain')
				}
			})
			printerJobs.print('')
		})
		
		let buffer = printerJobs.buffer();
		console.log('buffer>>>',buffer)
		printbuffs(buffer)
	}
	
	function printbuffs(buffer) {
		// 1.并行调用多次会存在写失败的可能性
		// 2.建议每次写入不超过20字节
		// 分包处理，延时调用 
		const maxChunk = 20;
		const delay = 20;
		for (let i = 0, j = 0, length = buffer.byteLength; i < length; i += maxChunk, j++) {
			let subPackage = buffer.slice(i, i + maxChunk <= length ? (i + maxChunk) : length);
			setTimeout(printbuff, j * delay, subPackage);
		}
	}
	
	function printbuff(buffer) {
		bluetooth.writeBLECharacteristicValue(buffer, writeId.value)
	}
	
	function printImg() {
		const printerJobs = new PrinterJobs();
		console.log(imgPixData.value.data)
		printerJobs.printImage(imgPixData.value.data)
	}
	
	// 打印题文
	function printTitleContent(printerJobs, textArr) {
		textArr.forEach(text => printerJobs.print(text))
	}
	
	
	// 打印答案、解析
	function printAnswerExplain (printerJobs, textArr, type) {
		if (type == 'answer') printerJobs.print('答案：');
		if (type == 'explain') printerJobs.print('解析：');
		textArr.forEach(text => printerJobs.print(text))
	}
	
	// 打印选项
	function printOption (printerJobs, options) {
		options.forEach(option => {
			option.textArr.forEach((text, index) => {
				const printText = index == 0 ? `${option.number}. ${text}` : text;
				printerJobs.print(printText)
			})
		})
	}
	
	// 格式化试题
	function formatQuestion (question) {
		// 提取img标签
		// 剔除img标签及内容并做标记
		// 根据br标签分割内容
		// 剔除html标签
		const ques = {
			content: {
				text: question.questioncontent,
				textArr: [],
				imgs: []
			},
			options: question.option.map(option => {
				return {
					number: option.optionnumber,
					text: option.optioncontent,
					textArr: [],
					imgs: []
				}
			}),
			answer: {
				text: question.questionanswer,
				textArr: [],
				imgs: []
			},
			explain: {
				text: question.questionexplain,
				textArr: [],
				imgs: []
			}
		}
		
		Object.keys(ques).forEach(key => {
			if (key == 'options') {
				ques[key].forEach(option => {
					const { imgArr, text } = formatImgText(option.text)
					option.text = text;
					option.textArr = formatTextTag(text);
					option.imgs = imgArr;
				})
				return;
			}
			const item = ques[key];
			const { imgArr, text } = formatImgText(item.text)
			item.text = text;
			item.textArr = formatTextTag(text)
			item.imgs = imgArr;
		})
		return ques;
	}
	
	function formatImgText (text) {
		const imgRegx = /<img\s*src=\"([^\"]*?)\"[^>]*>/;
		const imgRegxG = /<img\s*src=\"([^\"]*?)\"[^>]*>/g;
		const imgArr = text.match(imgRegxG) || [];
		let regText = text;
		imgArr.forEach((img, index) => {
			regText = text.replace(imgRegx, `#{img_${index}}`)
		})
		return {
			imgArr,
			text: regText
		}
	}
	
	function formatTextTag (text) {
		const textArr = text.split(/<br\s*\/?>/);
		textArr.forEach((item, index) => {
			textArr[index] = item.replace(/<[^>]*>/g, '')
		})
		return textArr;
	}
	
	function getImg () {
		const imgUrl = 'http://test6.jianxiaopu.com/img/ad.png';
		return getImgData(imgUrl)
		.then(data => {
			return getImageInfo(imgUrl)
		})
		.then(imgInfo => {
			const { width, height, path } = imgInfo;
			canvasH.value = height;
			canvasW.value = width;
			const canvas = uni.createCanvasContext('imgCanvas');
			canvas.drawImage(path, 0, 0, width, height)
			canvas.draw(false, () => {
				uni.canvasGetImageData({
					canvasId: 'imgCanvas',
					success: (pixData) => {
						imgPixData.value = pixData;
					}
				})
			})
		})
	}
	
	function getImageInfo(path) {
		return new Promise((resolve, reject) => {
			uni.getImageInfo({
				src: path,
				success: (imgInfo) => {
					resolve(imgInfo)
				},
				fail: (error) => {
					reject(error)
				}
			})
		})
	}
</script>

<style lang="scss" scoped>
@import './print.scss';
</style>
