/**
 * @export
 * @param {string} name 微信api的名称 ，如 uniAsyncPromise("getSystemInfo",options)
 * @param {object} options 除了success 和 fail 的其他参数
 * @returns
 */
export function uniAsyncPromise(name, options) {
	return new Promise((resolve, reject) => {
		uni[name]({
			...(options || {}),
			// ...options,
			success: (res) => {
				resolve(res);
			},
			fail: (err) => {
				reject(err);
			}
		});
	});
}
//微信小程序向蓝牙打印机发送数据进行打印的坑：
//小程序api向蓝牙打印机发送数据打印，发送的任何内容都应该要转成二进制数据，而且蓝牙打印的文本编码是GBK的，发送中文需转成GBK编码再转成二进制数据发送
//发送打印机指令也要转成二进制数据发送
//蓝牙打印机一次接收的二级制数据有限制，不同的系统不同的蓝牙设备限制可能不同，微信建议一次20个字节，需做递归分包发送
//发送完要打印的内容后，一定要发送一个打印的指令才能顺利打印 （有些指令就不需要）

//一、初始化蓝牙、开始检索蓝牙设备
// { allowDuplicatesKey: true, interval: 500}
export function openBlue() {
	return uniAsyncPromise('openBluetoothAdapter')
}

export function startBluetoothDevicesDiscovery(option) {
	console.log('开始蓝牙扫描');
	uniAsyncPromise('startBluetoothDevicesDiscovery', option).then((res) => {
		console.log('正在搜寻蓝牙设备', res);
	});
}

export function getConnectedBluetoothDevices(option) {
	console.log('开始获取已连接设备');
	return uniAsyncPromise('getConnectedBluetoothDevices', option)
}
//二、
/**
 *
 *
 * @export
 * @param {function} getDevices uni.getBluetoothDevices的监听回调函数
 */
export function onfindBlueDevices(getDevices) {
	//监听寻找到新设备的事件
	uni.onBluetoothDeviceFound((devices)=>{
		//获取在蓝牙模块生效期间所有已发现的蓝牙设备
		uniAsyncPromise('getBluetoothDevices').then((res) => {
			getDevices && getDevices(res.devices);
		});
	});
}

/**
 * @export
 * @param {function} stopBlueDevicesDiscovery 关闭蓝牙扫描
 */
export function stopBlueDevicesDiscovery() {
	//监听寻找到新设备的事件
	console.log('停止蓝牙扫描');
	return uniAsyncPromise('stopBluetoothDevicesDiscovery').then((res) => {
		console.log('停止搜寻蓝牙设备', res);
	});
}



//三、连接蓝牙设备
/**
 * @export
 * @param {function} createBLEConnection 
 * @param {number} deviceId 蓝牙设备id
 */
export function createBLEConnection(deviceId, sucess, fail) {
	//连接蓝牙设备
	console.log('连接蓝牙设备', deviceId);
	uniAsyncPromise("createBLEConnection", {
			deviceId,
			timeout: 10000
		})
		.then(res => {
			//连接成功可选择停止搜索蓝牙
			stopBlueDevicesDiscovery();
			console.log('连接成功');
			sucess && sucess({
				res: res,
			});
		})
		.catch(res => {
			console.log('连接设备异常' + res);
			fail && fail({
				res: res,
			});
		})
	/*.finally(res=>{
	    console.log('连接成功');
	    sucess && sucess({
	        res: res,
	    });
	});*/
}

export function closeBLEConnection(deviceId) {
	console.log('断开蓝牙设备', deviceId);
	uniAsyncPromise("closeBLEConnection", {
			deviceId
		})
		.then(res => {
			console.log('BLEDisconnect complete', res);
		})
		.catch(res => {
			console.log('断开设备异常' + res);
		})
	/*.finally(res=>{
	    console.log('BLEDisconnect complete', res);            
	});  */
}

//四、连接成功后， 获取蓝牙设备的service服务
// uniAsyncPromise("getBLEDeviceServices",{deviceId:""}).then(res=>{})
export function getBLEDeviceServices(deviceId, success, fail) {
	console.log('获取ServiceId', deviceId);
	//加延迟避免取不到service
	setTimeout(()=>{
		uniAsyncPromise("getBLEDeviceServices", {
			deviceId:deviceId
		})
		.then(res => {
			console.log('服务', res);
			success && success({
				serviceId: res.services,
			});
		})
		.catch((res) => {
			//getBLEDeviceServices(deviceId, success, fail);
			console.log('获取ServiceId异常' + res);
			fail && fail({
				res: res,
			});
		});
	},1000)
}

//五、获取的service服务可能有多个，递归获取特征值（最后要用的是能读，能写，能监听的那个值的uuid作为特征值id）
/**
 *
 *
 * @export
 * @param {number} deviceId 蓝牙设备id
 * @param {array} services uniAsyncPromise("getBLEDeviceServices",{deviceId:""}).then(res=>{})获取的res.services
 * @param {function} success 成功取得有用特征值uuid的回调函数
 */
export function getDeviceCharacteristics(deviceId, services, success, fail) {
	//services = services.slice(0);
	console.log('获取Characteristics', deviceId, services);
	if (services.length) {
		const serviceId = services.shift().uuid;
		console.log('ServceID ', serviceId);
		uniAsyncPromise('getBLEDeviceCharacteristics', {
				deviceId,
				serviceId,
			})
			.then((res) => {
				console.log('getBLEDeviceCharacteristics', deviceId, serviceId, res);
				let finished = false;
				let write = false;
				let notify = false;
				let indicate = false;
				var readId;
				var writeId;
				//有斑马品牌的一款打印机中res.characteristics的所有uuid都是相同的，找所有的properties存在(notify || indicate) && write这种情况就说明这个uuid是可用的（不确保所有的打印机都能用这种方式取得uuid,在主要测试得凯盛诺打印机res.characteristic只有一个uuid,所以也能用这个方式）
				for (var i = 0; i < res.characteristics.length; i++) {
					if (!notify) {
						notify = res.characteristics[i].properties.notify;
						if (notify) readId = res.characteristics[i].uuid;
					}
					if (!indicate) {
						indicate = res.characteristics[i].properties.indicate;
						if (indicate) readId = res.characteristics[i].uuid;
					}
					if (!write) {
						write = res.characteristics[i].properties.write;
						writeId = res.characteristics[i].uuid;
					}
					if ((notify || indicate) && write) {
						/* 获取蓝牙特征值uuid */
						success &&
							success({
								serviceId,
								writeId: writeId,
								readId: readId,
							});
						finished = true;
						break;
					}
				}

				if (!finished) {
					getDeviceCharacteristics(deviceId, services, success, fail);
				}
			})
			.catch((res) => {
				getDeviceCharacteristics(deviceId, services, success, fail);
			});
	} else {
		fail && fail();
	}
}

//六、启动notify 蓝牙监听功能 然后使用 uni.onBLECharacteristicValueChange用来监听蓝牙设备传递数据
/**
 * @export
 * @param {object} options
 * {
            deviceId,//蓝牙设备id
            serviceId,//服务id
            characteristicId,//可用特征值uuid
    }
 * @param {function} onChange 监听蓝牙设备传递数据回调函数
 */
export function onGetBLECharacteristicValueChange(options, onChange = function() {}) {
	console.log('deviceId ', options.deviceId);
	console.log('serviceId ', options.serviceId);
	console.log('characteristicId ', options.characteristicId);
	uniAsyncPromise('notifyBLECharacteristicValueChange', {
		state: true,
		...options,
	}).then((res) => {
		console.log('onBLECharacteristicValueChange ');
		uni.onBLECharacteristicValueChange(onChange);
	});
}

//七、发送数据(递归分包发送)
/**
 * @export
 * @param {object} options
 * {
            deviceId,
            serviceId,
            characteristicId,
			value [ArrayBuffer],
			lasterSuccess,
    }
 */
export function senBlData(deviceId, serviceId, characteristicId,uint8Array,lasterSuccess,lasterError) {
	console.log('************deviceId = [' + deviceId + ']  serviceId = [' + serviceId + '] characteristics=[' +characteristicId+ "]")
	var uint8Buf = Array.from(uint8Array);
	function split_array(datas,size){
		var result = {};
		var j = 0
		if(datas.length < size) {
			size = datas.length
		}
		for (var i = 0; i < datas.length; i += size) {
			result[j] = datas.slice(i, i + size)
			j++
		}
		return result
	}
	var sendloop = split_array(uint8Buf, 20);
	console.log(sendloop.length)
	function realWriteData(sendloop, i) {
		var data = sendloop[i]
		if(typeof(data) == "undefined"){
			lasterSuccess()
			return
		}
		//console.log("第【" + i + "】次写数据"+data)
		var buffer = new ArrayBuffer(data.length)
		var dataView = new DataView(buffer)
		for (var j = 0; j < data.length; j++) {
			dataView.setUint8(j, data[j]);
		}
		uni.writeBLECharacteristicValue({
			deviceId,
			serviceId,
			characteristicId,
			value: buffer,
			success(res) {
				console.log('发送成功',i)
				setTimeout(()=>{
					realWriteData(sendloop, i + 1);
				},100)
			},
			fail(e) {
				console.log('发送数据失败',e)
				lasterError()
			}
		})
	}
   var i = 0;
	realWriteData(sendloop, i);
}
// cpcl 发送数据
export function sendDataToDevice(options) {
	let byteLength = options.value.byteLength;
	//这里默认一次20个字节发送
	const speed = plus.os.name != 'Android' ? 180 : 15; //20; 
	console.log("send data 20");
	console.log(options,byteLength,options.value);
	if (byteLength > 0) {
		uniAsyncPromise('writeBLECharacteristicValue', {
				...options,
				value: options.value.slice(0, byteLength > speed ? speed : byteLength),
			})
			.then((res) => {
				if (byteLength > speed) {
					setTimeout(()=>{
						sendDataToDevice({
							...options,
							value: options.value.slice(speed, byteLength),
						});
					},50)
				} else {
					options.lasterSuccess && options.lasterSuccess();
				}
			})
			.catch((res) => {
				console.log(res);
				options.lasterError && options.lasterError();
			});
	}
} 
/**
 * toast显示捕获的蓝牙异常
 */
export function catchToast(err) {
	const errMsg = {
		10000: '未初始化蓝牙模块',
		10001: '蓝牙未打开,请打开蓝牙开关',
		10002: '没有找到指定设备',
		10003: '连接失败',
		10004: '没有找到指定服务',
		10005: '没有找到指定特征值',
		10006: '当前连接已断开',
		10007: '当前特征值不支持此操作',
		10008: '系统上报异常',
		10009: '系统版本低于 4.3 不支持BLE',
		10012: '连接超时,请重试'
	};
	let coode = err.errCode ? err.errCode.toString() : '';
	let msg = errMsg[coode];
	plus.nativeUI.toast(msg || coode, {
		align: 'center',
		verticalAlign: 'center',
		duration:'long'
	});
}
