// 灵敏度
const BLEDIS = 0.9;


// 设备Id
var deviceId = "";
// 服务Id
var serviceId = "";

var notifyCharacteristicId = "";

var writeCharacteristicId = "";

var currentInstruction = "";

var showToast = false;

var bListenerUpdate = false;

var bListenerJson = false;

var bListenerMac = false;

function initData() {
	// 设备Id
	this.deviceId = "";
	// 服务Id
	this.serviceId = "";

	this.notifyCharacteristicId = "";

	this.writeCharacteristicId = "";

	this.currentInstruction = "";

	this.showToast = false;

	this.bListenerUpdate = false;

	this.bListenerJson = false;

	this.bListenerMac = false;

}


function openBluetoothAdapter(context) {

	let {
		success,
		fail,
		complete
	} = context;

	//#ifdef H5
	console.warn('h5不加载蓝牙模块');
	return;
	//#endif

	let self = this;
	// 初始化蓝牙适配器
	uni.openBluetoothAdapter({
		success: res => {
			// console.log("初始化蓝牙成功：", res);
			if (success)
				success(res);
		},
		fail: res => {
			// console.error("openBluetoothAdapter == ", res);
			if (fail)
				fail(res);
		},
		complete: res => {
			// console.warn("************openBluetoothAdapter complete == ", res);
			if (complete)
				complete(res);
		}
	})
}

function onBLEConnectionStateChange() {
	//#ifdef H5
	console.warn('h5不加载蓝牙模块');
	return;
	//#endif

	uni.onBLEConnectionStateChange(res => {
		// 该方法回调中可以用于处理连接意外断开等异常情况
		console.log(`蓝牙连接状态 -------------------------->`, JSON.stringify(res));
		if (!res.connected) {
			// if (this.isStop) return;
			// console.log('断开低功耗蓝牙成功:');
			uni.$emit('callbackCloseBLE');
			//todo 在这里尝试重连
			//关闭连接
			// this.closeBluetoothAdapter();
		}
	});
}

/**
 * 连接低功耗蓝牙设备。
 * 若APP在之前已有搜索过某个蓝牙设备，并成功建立连接，可直接传入之前搜索获取的 deviceId 直接尝试连接该设备，无需进行搜索操作。
 */
function createBLEConnection(item, success, fail) {
	let self = this;
	self.initData();
	self.deviceId = item.deviceId;
	let timeout = 10000;
	uni.createBLEConnection({
		// 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
		deviceId: self.deviceId,
		timeout,
		success: res => {
			if (success) {
				success(res);
			}
		},
		fail: res => {
			if (fail)
				fail(res);
		}
	});


}

/**
 * 获取设备的服务ID
 */
function getBLEDeviceServices(item, callback,getServiceList) {
	let serviceList = [];
	let self = this;
	// console.log("getBLEDeviceServices");
	uni.getBLEDeviceServices({
		deviceId: item.deviceId,
		success: res => {
			console.log("getBLEDeviceServices==", JSON.stringify(res), item);
			serviceList = res.services;
			if(serviceList.length == 0){
				uni.hideToast();
				uni.showModal({
					title:'失败',
					content:'获取服务失败，请尝试重新连接对应的模式。'
				})
			}
			if(getServiceList){
				getServiceList(serviceList);
			}
			for (let i = 0; i < serviceList.length; i++) {
				let service = serviceList[i];
				//比对service是否是F393服务
				// if (item.primaryUUID && service.uuid.indexOf(item.primaryUUID) != -1) 
				if (service.uuid.toLocaleLowerCase() === item.PRIMARY_SERVICE.toLocaleLowerCase()) {
					self.serviceId = service.uuid;
					// console.log("设备的serviceId： " + self.serviceId);
					//开始获取指定服务的特征值
					self.getBLEDeviceCharacteristics(item, callback);
					break;
				}
			}
		},
		fail: failRes => {
			console.log('device services:', failRes.services)
			uni.showModal({
				title:'连接失败',
				content:'未获取到相应服务,请继续尝试连接设备。'
			})
		}
	});
}
/**
 * 获取指定服务的特征值
 */
function getBLEDeviceCharacteristics(item, callback) {
	let deviceId = this.deviceId;
	let serviceId = this.serviceId;
	let characteristicsList = [];
	let self = this;
	uni.getBLEDeviceCharacteristics({
		deviceId,
		serviceId,
		success: res => {
			// console.log(JSON.stringify(res));
			// console.log("获取的" + serviceId + "服务的特征值：" + JSON.stringify(res.characteristics)+JSON.stringify(item));
			// console.log(res.characteristics);
			// console.log(item);
			// characteristicsList = res.characteristics;
			// for (let i = 0; i < characteristicsList.length; i++) {
			// 	let characteristic = characteristicsList[i];
			// 	//该特征值是否支持 notify或indicate 操作
			// 	if (characteristic.properties.notify || characteristic.properties.indicate) {
			// 		console.log("该特征值支持 notify 操作:" + characteristic.uuid);
			// 		self.notifyCharacteristicId = characteristic.uuid;
			// 		self.notifyBLECharacteristicValueChange(deviceId, serviceId);
			// 	}
			// 	if (characteristic.properties.write) {
			// 		console.log("该特征值支持 write 操作:" + characteristic.uuid);
			// 		self.writeCharacteristicId = characteristic.uuid;
			// 		// break;
			// 	}
			// }
			if (item.PRIMARY_NOTIFY != '') {
				self.notifyCharacteristicId = item.PRIMARY_NOTIFY;
				self.notifyBLECharacteristicValueChange(callback);
			}
			if (item.PRIMARY_WRITE != '') {
				self.writeCharacteristicId = item.PRIMARY_WRITE;
			}
		},
		fail: res => {
			console.log('device getBLEDeviceCharacteristics failed:', JSON.stringify(res))
		}
	})
}

//启用低功耗蓝牙设备特征值变化时的 notify 功能，订阅特征值。
//注意：必须设备的特征值支持notify或者indicate才可以成功调用，具体参照 characteristic 的 properties 属性
function notifyBLECharacteristicValueChange(callback) {
	var _self = this;
	// 启用notify功能
	// console.log("启用notify功能");
	uni.notifyBLECharacteristicValueChange({
		state: true,
		deviceId: _self.deviceId,
		serviceId: _self.serviceId,
		characteristicId: _self.notifyCharacteristicId,
		success: function(res) {
			_self.onBLECharacteristicValueChange(callback); //监听特征值变化
		},
		fail: function(res) {
			uni.showToast({
				title: 'notify启动失败',
				icon: "none",
				mask: true
			});

		}
	})
}
//监听低功耗蓝牙设备的特征值变化。必须先启用notify接口才能接收到设备推送的notification。
function onBLECharacteristicValueChange(callback) {
	var self = this;
	console.log("onBLECharacteristicValueChange success");
	if (callback) {
		callback({
			notifyCharacteristicId: self.notifyCharacteristicId,
			writeCharacteristicId: self.writeCharacteristicId
		})
	}
	uni.onBLECharacteristicValueChange(function(res) {
		let box = {};
		var resValue = ab2hext(res.value); //16进制字符串
		// console.log(self.currentInstruction +","+ self.bListenerUpdate+","+self.bListenerJson);

		if (self.currentInstruction == "V" && self.showToast) {
			var resValueStr = hexToString(resValue);
			// console.log("v resValueStr：" + resValueStr);
			// uni.showToast({
			// 	title: resValueStr.replace(/\{|}/g,'').trim(),
			// 	icon: 'none',
			// 	duration: 5000
			// })
			let _info = {
				type: 'version',
				instruction: 'V',
				value: resValueStr.replace(/\{|}/g, '').trim()
			}
			uni.$emit('listenerBLE', _info);
			self.currentInstruction = "";
			self.showToast = false;
			return;
		} else if (self.currentInstruction == 'M' && self.bListenerMac) {
			var resValueStr = hexToString(resValue);
			// console.log(resValue);
			// console.log("m:", resValueStr.replace(/\{|}/g,''));
			// uni.showToast({
			// 	title: resValueStr.replace(/\{|}/g,'').trim(),
			// 	icon: 'none',
			// 	duration: 5000
			// })
			let _info = {
				type: 'mac',
				instruction: 'M',
				value: resValueStr.replace(/\{|}/g, '').trim()
			}
			uni.$emit('listenerBLE', _info);
			self.currentInstruction = "";
			self.bListenerMac = false;
			return;
		}
		//步数数据解析
		if (self.bListenerJson) {
			var resValueStr = hexToString(resValue);
			// let _info = {
			// 	type: 'mac',
			// 	instruction: 'M',
			// 	value: resValueStr.replace(/\{|}/g, '').trim()
			// }
			console.log(resValueStr);
			box["Json"] = resValueStr;
			uni.$emit('updateBLEDeviceJson', box);
		}
		//原始数据解析
		if (self.bListenerUpdate) {
			// console.log("min:" + min+",s:"+s+",ms:"+ms);

			//R/L 左手还是右手
			let handle = resValue.substr(6, 2);

			let axStr = resValue.substr(8, 4);
			let ayStr = resValue.substr(12, 4);
			let azStr = resValue.substr(16, 4);
			// console.log("accStr：" + axStr+","+ayStr+","+azStr);
			// console.log("hex2int：" + hexToSignedInt(axStr)+","+hexToSignedInt(ayStr)+","+hexToSignedInt(azStr));
			//一个字节最大只能表示265  2个字节可以表示65536  然后你这边做一下转换 例如00 3E   3*16+14=62 ----->0.03  g 
			//(真实值= AD值 /32768  * 16)
			//0.003 = 62 / 2768  * 16
			let ax = hexToSignedInt(axStr) / 32768 * 16;
			let ay = hexToSignedInt(ayStr) / 32768 * 16;
			let az = hexToSignedInt(azStr) / 32768 * 16;

			let gxStr = resValue.substr(20, 4);
			let gyStr = resValue.substr(24, 4);
			let gzStr = resValue.substr(28, 4);

			//角速度(AD值/32768 * 2000) 角速度单位是 °/s  范围是 正负2000
			let gx = hexToSignedInt(gxStr) / 32768 * 2000;
			let gy = hexToSignedInt(gyStr) / 32768 * 2000;
			let gz = hexToSignedInt(gzStr) / 32768 * 2000;

			//毫秒
			let ms = hex2int(resValue.substr(2, 4));
			//分
			let min = hex2int(resValue.substr(32, 2));
			//秒
			let s = hex2int(resValue.substr(34, 2));

			box["handle"] = hexToString(handle);
			box["acc"] = {
				ax,
				ay,
				az
			};
			box["gyro"] = {
				gx,
				gy,
				gz
			};

			box["min"] = min;
			box["s"] = s;
			box["ms"] = ms;


			// console.log("box：" + JSON.stringify(box));

			// if (typeof obj !== 'object' && obj) {
			// 	// console.log("连接错误")
			// 	//-1为错误
			// 	uni.$emit("callbackBLEState", {
			// 		state: -1,
			// 		msg: "设备数据错误"
			// 	});
			// 	return;
			// }
			// if (obj.hasOwnProperty("H")) {
			// 	console.log("HHHH:", obj.H);
			// }
			//更新数据给webview,在game-play-web||game-play-sub绑定
			//后面更新数据都用此接口
			uni.$emit('updateBLEDeviceData', box);
		}


	});
}

// ArrayBuffer转16进制字符串示例
function ab2hext(buffer) {
	var hexArr = Array.prototype.map.call(
		new Uint8Array(buffer),
		function(bit) {
			return ('00' + bit.toString(16)).slice(-2)
		}
	)
	return hexArr.join('');
}
// 字符串转为ArrayBuffer对象，参数为字符串
function str2ab(str) {
	var buf = new ArrayBuffer(str.length * 2); // 每个字符占用2个字节
	var bufView = new Uint16Array(buf);
	for (var i = 0, strLen = str.length; i < strLen; i++) {
		bufView[i] = str.charCodeAt(i);
	}
	return buf;
}
//16进制的字符串 转换为整数
function hex2int(hex) {
	var len = hex.length,
		a = new Array(len),
		code;
	for (var i = 0; i < len; i++) {
		code = hex.charCodeAt(i);
		if (48 <= code && code < 58) {
			code -= 48;
		} else {
			code = (code & 0xdf) - 65 + 10;
		}
		a[i] = code;
	}

	return a.reduce(function(acc, c) {
		acc = 16 * acc + c;
		return acc;
	}, 0);
}
//16进制转有符号的整数
function hexToSignedInt(hex) {
	let two = parseInt(hex, 16).toString(2);
	let bitNum = hex.length * 4;
	if (two.length < bitNum) {
		while (two.length < bitNum) {
			two = "0" + two;
		}
	}

	if (two.substring(0, 1) == "0") {
		two = parseInt(two, 2);

		return two;
	} else {
		let two_unsign = "";
		two = parseInt(two, 2) - 1;
		two = two.toString(2);
		two_unsign = two.substring(1, bitNum);
		two_unsign = two_unsign.replace(/0/g, "z");
		two_unsign = two_unsign.replace(/1/g, "0");
		two_unsign = two_unsign.replace(/z/g, "1");
		two = parseInt(-two_unsign, 2);

		return two;
	}
}

//十六进制转ASCII码
function hexCharCodeToStr(hexCharCodeStr) {
	var trimedStr = hexCharCodeStr.trim();
	var rawStr = trimedStr.substr(0, 2).toLowerCase() === "0x" ? trimedStr.substr(2) : trimedStr;
	var len = rawStr.length;
	if (len % 2 !== 0) {
		alert("存在非法字符!");
		return "";
	}
	var curCharCode;
	var resultStr = [];
	for (var i = 0; i < len; i = i + 2) {
		curCharCode = parseInt(rawStr.substr(i, 2), 16);
		resultStr.push(String.fromCharCode(curCharCode));
	}
	return resultStr.join("");
}

//ASCII码转16进制
function strToHexCharCode(str) {
	if (str === "") {
		return "";
	} else {
		var hexCharCode = [];
		hexCharCode.push("0x");
		for (var i = 0; i < str.length; i++) {
			hexCharCode.push((str.charCodeAt(i)).toString(16));
		}
		return hexCharCode.join("");
	}
}

//16进制转字符串
function hexToString(str) {
	var trimedStr = str.trim();
	var rawStr =
		trimedStr.substr(0, 2).toLowerCase() === "0x" ?
		trimedStr.substr(2) :
		trimedStr;
	var len = rawStr.length;
	if (len % 2 !== 0) {
		// alert("Illegal Format ASCII Code!");
		return "";
	}
	var curCharCode;
	var resultStr = [];
	for (var i = 0; i < len; i = i + 2) {
		curCharCode = parseInt(rawStr.substr(i, 2), 16); // ASCII Code Value
		resultStr.push(String.fromCharCode(curCharCode));
	}
	return resultStr.join("");
}


/**
 * 断开蓝牙模块连接
 */
function closeBluetoothAdapter() {
	//#ifdef H5
	console.warn('h5不加载蓝牙模块');
	return;
	//#endif

	uni.closeBluetoothAdapter({
		success: res => {
			console.log('断开蓝牙模块成功');

			uni.showToast({
				icon: "none",
				title: "蓝牙已经断开！",
				mask: false,
				duration: 3000
			});
		}
	});
}


//向低功耗蓝牙设备特征值中写入二进制数据。注意：必须设备的特征值支持 write 才可以成功调用。
function writeBLECharacteristicValue(value, retryCount, success, getFail) {
	var self = this;
	if (!value && value === '') {
		uni.showToast({
			title: "指令为空"
		})
		return;
	}
	//记录一下指令
	self.currentInstruction = value;
	//V 获取版本，M 获取mac 地址
	if (value == "V")
		self.showToast = true;

	if (value == "M") {
		self.showToast = true;
		self.bListenerMac = true;
	}
	if (value == "4") {
		self.bListenerUpdate = false;
	}
	if (value == "3") {
		if (self.bListenerUpdate) {
			uni.showToast({
				title: "原始数据已开启"
			})
			return;
		}
		self.bListenerUpdate = true;
	}

	if (value == "6") {
		self.bListenerJson = false;
	}
	if (value == "5") {
		if (self.bListenerJson) {
			uni.showToast({
				title: "步数数据已开启"
			})
			return;
		}
		self.bListenerJson = true;
	}


	console.log("currentInstruction:", self.currentInstruction, value, self.bListenerUpdate, self.bListenerMac);
	console.log("self.deviceId:", self.deviceId, self.serviceId, self.writeCharacteristicId);
	uni.writeBLECharacteristicValue({
		deviceId: self.deviceId,
		serviceId: self.serviceId,
		// 这里的 characteristicId 需要在 getBLEDeviceCharacteristics 接口中获取
		characteristicId: self.writeCharacteristicId,
		// 这里的value是ArrayBuffer类型
		value: str2ab(value),
		success:(res)=> {
			console.log('writeBLECharacteristicValue success', res.errMsg, value,retryCount);
			if (success) {
				success(res);
			}
		},
		fail: (fail) => {
			console.log(fail)
			//重新写入
			// uni.showModal({
			// 	title:"提示",
			// 	content:"蓝牙通信失败，是否重新执行此操作。",
			// 	success: (resValue) => {
			// 		if(resValue.confirm){
			// 			self.writeBLECharacteristicValue(value, success);
			// 		}
			// 	}
			// })
			if(retryCount>0){
				console.log("writeBLECharacteristicValue Rewrite ===================>"+value+" == "+retryCount);
				self.writeBLECharacteristicValue(value,retryCount,success,getFail);
				retryCount--;
			}
			if(getFail){
				getFail(fail);
			}
		},
		complete: (completeRes) => {
			
			console.log(completeRes)
		}
	})
	
	// uni.readBLECharacteristicValue({
	// 	deviceId:self.deviceId,
	// 	serviceId:self.serviceId,
	// 	characteristicId:self.notifyCharacteristicId,
	// 	success: (resValue) => {
	// 		console.log('read success!');
	// 	}
	// })
}

/**
 * 断开蓝牙连接
 */
function closeBLEConnection(deviceId, success) {
	uni.closeBLEConnection({
		deviceId,
		success: res => {
			if (success)
				success();
		},
		fail: (fail) => {
			console.log("关闭蓝牙失败",fail);
		}
	});
}

function getRSSITransDistance(rssi) {
	return Math.pow(Math.E, (Math.abs(rssi) - 66.78) / 16.56);
}

/**
 * 获取在蓝牙模块生效期间所有已发现的蓝牙设备。包括已经和本机处于连接状态的设备。
 */
function getBluetoothDevices() {
	uni.getBluetoothDevices({
		success(res) {
			console.log("getBluetoothDevices:", res)
		}
	})
}

export default {
	deviceId,
	serviceId,
	//蓝牙模块
	openBluetoothAdapter,
	closeBluetoothAdapter,

	onBLEConnectionStateChange,
	getBLEDeviceCharacteristics,
	notifyBLECharacteristicValueChange,
	onBLECharacteristicValueChange,

	//建立连接模块
	createBLEConnection,
	closeBLEConnection,

	getBLEDeviceServices,
	getRSSITransDistance,

	BLEDIS,

	//写入模块数据
	writeBLECharacteristicValue,

	//获取已经匹配的蓝牙
	getBluetoothDevices,
	//初始化this变量
	initData

}
