/**
 * html+ 串口蓝牙操作
 * 2021.04.23 uni-app版本
 * @auth boolTrue
 */

/**
 * 初始化参数
 */ 
//#ifdef APP-PLUS
let BluetoothAdapter = plus.android.importClass("android.bluetooth.BluetoothAdapter");
let Intent = plus.android.importClass("android.content.Intent");
let IntentFilter = plus.android.importClass("android.content.IntentFilter");
let BluetoothDevice = plus.android.importClass("android.bluetooth.BluetoothDevice");
let UUID = plus.android.importClass("java.util.UUID");
let Toast = plus.android.importClass("android.widget.Toast");
var Manifest = plus.android.importClass("android.Manifest"); 
//连接串口设备的 UUID
let MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");

let invoke = plus.android.invoke;
let btAdapter = BluetoothAdapter.getDefaultAdapter();
let activity = plus.android.runtimeMainActivity();

let btSocket = null;
let btInStream = null;
let btOutStream = null;
let setIntervalId = 0;

let btFindReceiver = null; //蓝牙搜索广播接收器
let btStatusReceiver = null; //蓝牙状态监听广播
//#endif
/**
 * 构造对象
 */ 
var blueToothTool = {
	state : {
		bluetoothEnable: false, //蓝牙是否开启
		bluetoothState: "", //当前蓝牙状态
		discoveryDeviceState: false, //是否正在搜索蓝牙设备
		readThreadState: false, //数据读取线程状态
		popview: null
	},
	options : {
		/**
		 * 监听蓝牙状态回调
		 * @param {String} state
		 */
		listenBTStatusCallback: function(state) {},
		/**
		 * 搜索到新的蓝牙设备回调
		 * @param {Device} newDevice
		 */
		discoveryDeviceCallback: function(newDevice) {},
		/**
		 * 蓝牙搜索完成回调
		 */
		discoveryFinishedCallback: function() {},
		/**
		 * 接收到数据回调
		 * @param {Array} dataByteArr
		 */
		readDataCallback: function(dataByteArr) {},
		/**
		 * 蓝牙连接中断回调
		 * @param {Exception} e
		 */
		connExceptionCallback: function(e) {}
	},
	init(setOptions) {
		Object.assign(this.options, setOptions);
		this.state.bluetoothEnable = this.getBluetoothStatus();
		if(!this.state.bluetoothEnable) this.options.listenBTStatusCallback && this.options.listenBTStatusCallback('STATE_OFF_First');
		this.listenBluetoothStatus();
	},
	shortToast(msg) {
		Toast.makeText(activity, msg, Toast.LENGTH_SHORT).show();
	},
	/**
	 * 是否支持蓝牙
	 * @return {boolean}
	 */
	isSupportBluetooth() {
		if(btAdapter != null) {
			return true;
		}
		return false;
	},
	/**
	 * 获取蓝牙的状态
	 * @return {boolean} 是否已开启
	 */
	getBluetoothStatus() {
		if(btAdapter != null) {
			return btAdapter.isEnabled();
		}
		return false;
	},
	/**
	 * 打开蓝牙
	 * @param activity
	 * @param requestCode
	 */
	turnOnBluetooth() {
		if(btAdapter == null) {
			this.shortToast("没有蓝牙");
			return;
		}
		if(!btAdapter.isEnabled()) {
			if(activity == null) {
				this.shortToast("未获取到activity");
				return;
			} else {
				let intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
				let requestCode = 1;
				activity.startActivityForResult(intent, requestCode);
				return;
			}
		} else {
			this.shortToast("蓝牙已经打开");
		}
	},
	/**
	 * 关闭蓝牙
	 */
	turnOffBluetooth() {
		if(btAdapter != null && btAdapter.isEnabled()) {
			btAdapter.disable();
		}
		if(btFindReceiver != null) {
			try {
				activity.unregisterReceiver(btFindReceiver);
			} catch(e) {

			}
			btFindReceiver = null;
		}
		this.state.bluetoothEnable = false;
		this.cancelDiscovery();
		closeBtSocket();

		if(btAdapter != null && btAdapter.isEnabled()) {
			btAdapter.disable();
			this.shortToast("蓝牙关闭成功");
		} else {
			this.shortToast("蓝牙已经关闭");
		}
	},
	/**
	 * 获取已经配对的设备
	 * @return {Array} connetedDevices
	 */
	getPairedDevices() {
		let pairedDevices = [];

		//蓝牙连接android原生对象，是一个set集合
		let pairedDevicesAndroid = null;
		if(btAdapter != null && btAdapter.isEnabled()) {
			pairedDevicesAndroid = btAdapter.getBondedDevices();
		} else {
			this.shortToast("蓝牙未开启");
		}

		if(!pairedDevicesAndroid) {
			return pairedDevices;
		}

		//遍历连接设备的set集合，转换为js数组
		let it = invoke(pairedDevicesAndroid, "iterator");
		while(invoke(it, "hasNext")) {
			let device = invoke(it, "next");
			pairedDevices.push({
				"name": invoke(device, "getName"),
				"address": invoke(device, "getAddress"),
				device
			});
		}
		return pairedDevices;
	},
	/**
	 * 发现设备
	 */
	discoveryNewDevice() {
		if(btFindReceiver != null) {
			try {
				activity.unregisterReceiver(btFindReceiver);
			} catch(e) {
				console.error(e);
			}
			btFindReceiver = null;
			this.cancelDiscovery();
		}
		let Build = plus.android.importClass("android.os.Build");
		console.log('Build', Build.VERSION.SDK_INT)
		 //6.0以后的如果需要利用本机查找周围的wifi和蓝牙设备, 申请权限
		if (Build.VERSION.SDK_INT >= 6.0) {
			const location = activity.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION)
			if (location === -1) {
				plus.android.requestPermissions(['android.permission.ACCESS_COARSE_LOCATION'], e => {
					if (e.deniedPresent.length > 0 || e.deniedAlways.length > 0) { // 权限被拒绝或永久拒绝就给提示
						uni.showToast({
							icon: 'none',
							title: '有必要权限未获得，请在设置中打开'
						})
					} else if (e.granted.length > 0) {
						
					}
				})
			}
			if (activity.checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) === -1) {
				plus.android.requestPermissions(['android.permission.ACCESS_FINE_LOCATION'], e => {
					if (e.deniedPresent.length > 0 || e.deniedAlways.length > 0) { // 权限被拒绝或永久拒绝就给提示
						uni.showToast({
							icon: 'none',
							title: '有必要权限未获得，请在设置中打开'
						})
					} else if (e.granted.length > 0) {
						
					}
				})
			}
			if (activity.checkSelfPermission(Manifest.permission.BLUETOOTH) === -1) {
				plus.android.requestPermissions(['android.permission.BLUETOOTH'], e => {
					if (e.deniedPresent.length > 0 || e.deniedAlways.length > 0) { // 权限被拒绝或永久拒绝就给提示
						uni.showToast({
							icon: 'none',
							title: '有必要权限未获得，请在设置中打开'
						})
					} else if (e.granted.length > 0) {
						
					}
				})
			}
			if (activity.checkSelfPermission(Manifest.permission.BLUETOOTH_ADMIN) === -1) {
				plus.android.requestPermissions(['android.permission.BLUETOOTH_ADMIN'], e => {
					if (e.deniedPresent.length > 0 || e.deniedAlways.length > 0) { // 权限被拒绝或永久拒绝就给提示
						uni.showToast({
							icon: 'none',
							title: '有必要权限未获得，请在设置中打开'
						})
					} else if (e.granted.length > 0) {
						
					}
				})
			}
		}
		let options = this.options
		let that = this
		btFindReceiver = plus.android.implements("io.dcloud.android.content.BroadcastReceiver", {
			"onReceive": function(context, intent) {
				plus.android.importClass(context);
				plus.android.importClass(intent);
				let action = intent.getAction();
				
				if(BluetoothDevice.ACTION_FOUND == action) { // 找到设备
					let device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
					console.log('device11', device)
					let newDevice = {
						"name": plus.android.invoke(device, "getName"),
						"address": plus.android.invoke(device, "getAddress"),
						"type": plus.android.invoke(device, "getType"),
					}
					options.discoveryDeviceCallback && options.discoveryDeviceCallback(newDevice);
				}
				if(BluetoothAdapter.ACTION_DISCOVERY_FINISHED == action) { // 搜索完成
					that.cancelDiscovery();
					if (btSocket) {
						options.discoveryFinishedCallback && options.discoveryFinishedCallback(btSocket.isConnected())
					} else {
						options.discoveryFinishedCallback && options.discoveryFinishedCallback()
					}
				}
			}
		});
		let filter = new IntentFilter();
		filter.addAction(BluetoothDevice.ACTION_FOUND);
		filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
		activity.registerReceiver(btFindReceiver, filter);
		btAdapter.startDiscovery(); //开启搜索
		this.state.discoveryDeviceState = true;
	},
	/**
	 * 蓝牙状态监听
	 * @param {Activity} activity
	 */
	listenBluetoothStatus() {
		if(btStatusReceiver != null) {
			try {
				activity.unregisterReceiver(btStatusReceiver);
			} catch(e) {
				console.error(e);
			}
			btStatusReceiver = null;
		}
		btStatusReceiver = plus.android.implements("io.dcloud.android.content.BroadcastReceiver", {
			"onReceive": (context, intent)=> {
				plus.android.importClass(context);
				plus.android.importClass(intent);

				let action = intent.getAction();
				switch(action) {
					case BluetoothAdapter.ACTION_STATE_CHANGED:
						let blueState = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, 0);
						let stateStr = "";
						switch(blueState) {
							case BluetoothAdapter.STATE_TURNING_ON:
								stateStr = "STATE_TURNING_ON";
								break;
							case BluetoothAdapter.STATE_ON:
								this.state.bluetoothEnable = true;
								stateStr = "STATE_ON";
								break;
							case BluetoothAdapter.STATE_TURNING_OFF:
								stateStr = "STATE_TURNING_OFF";
								break;
							case BluetoothAdapter.STATE_OFF:
								stateStr = "STATE_OFF";
								this.state.bluetoothEnable = false;
								break;
						}
						this.state.bluetoothState = stateStr;
						this.options.listenBTStatusCallback && this.options.listenBTStatusCallback(stateStr);
						break;
				}
			}
		});
		let filter = new IntentFilter();
		filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
		activity.registerReceiver(btStatusReceiver, filter);
		// 首次连接 状态回调
		if(this.state.bluetoothEnable) {
			this.options.listenBTStatusCallback && this.options.listenBTStatusCallback('STATE_ON');
		}
	},
	/**
	 * 根据蓝牙地址，连接设备
	 * @param {Stirng} address
	 * @return {Boolean}
	 */
	connDevice(address, callback) {
		let InputStream = plus.android.importClass("java.io.InputStream");
		let OutputStream = plus.android.importClass("java.io.OutputStream");
		let BluetoothSocket = plus.android.importClass("android.bluetooth.BluetoothSocket");

		this.cancelDiscovery();
		if(btSocket != null) {
			this.closeBtSocket();
		}
		this.state.readThreadState = false;

		try {
			let device = invoke(btAdapter, "getRemoteDevice", address);
			btSocket = invoke(device, "createRfcommSocketToServiceRecord", MY_UUID);
		} catch(e) {
			console.error(e);
			this.shortToast("连接失败，获取Socket失败！");
			callback(false)
			return false;
		}
		try {
			btSocket.connect()
			this.readData();
		} catch(e) {
			console.error(e);
			this.shortToast("连接失败");
			callback(false)
			try {
				btSocket.close();
				btSocket = null;
			} catch(e1) {
				console.error(e1);
			}
			return false;
		}
		return true;
	},

	/**
	 * 根据配对连接
	 * @param {Stirng} address
	 * @return {Boolean}
	 */
	 connPairDevice(device, callback) {
		let InputStream = plus.android.importClass("java.io.InputStream");
		let OutputStream = plus.android.importClass("java.io.OutputStream");
		let BluetoothSocket = plus.android.importClass("android.bluetooth.BluetoothSocket");
		if(btSocket != null) {
			this.closeBtSocket();
		}
		this.state.readThreadState = false;

		try {
			console.log('device', device) 
			btSocket = invoke(device, "createRfcommSocketToServiceRecord", MY_UUID);
		} catch(e) {
			console.error(e);
			this.shortToast("连接失败，获取Socket失败！");
			callback(false)
			return false;
		}
		try {
			invoke(btSocket, "connect");
			this.readData(); //读数据
			this.shortToast("连接成功");
			callback(true)
		} catch(e) {
			console.error(e);
			this.shortToast("连接失败");
			callback(false)
			try {
				btSocket.close();
				btSocket = null;
			} catch(e1) {
				console.error(e1);
			}
			return false;
		}
		return true;
	},
	/**
	 * 断开连接设备
	 * @param {Object} address
	 * @return {Boolean}
	 */
	disConnDevice() {
		if(btSocket != null) {
			this.closeBtSocket();
		}
		this.state.readThreadState = false;
		this.shortToast("断开连接成功");
	},
	/**
	 * 断开连接设备
	 * @param {Object} address
	 * @return {Boolean}
	 */
	closeBtSocket() {
		this.state.readThreadState = false;
		if(!btSocket) {
			return;
		}
		try {
			btSocket.close();
		} catch(e) {
			console.error(e);
			btSocket = null;
		}
	},
	/**
	 * 取消发现
	 */
	cancelDiscovery() {
		if(btAdapter.isDiscovering()) {
			btAdapter.cancelDiscovery();
		}
		if(btFindReceiver != null) {
			activity.unregisterReceiver(btFindReceiver);
			btFindReceiver = null;
		}
		this.state.discoveryDeviceState = false;
	},
	/**
	 * 读取数据
	 * @param {Object} activity
	 * @param {Function} callback
	 * @return {Boolean}
	 */
	readData() {
		if(!btSocket) {
			this.shortToast("请先连接蓝牙设备！");
			return false;
		}
		try {
			btInStream = invoke(btSocket, "getInputStream");
			btOutStream = invoke(btSocket, "getOutputStream");
			console.log('btOutStream', btOutStream)
		} catch(e) {
			console.error(e);
			this.shortToast("创建输入输出流失败！");
			this.closeBtSocket();
			return false;
		}
		this.read();
		this.state.readThreadState = true;
		return true;
	},
	/**
	 * 模拟java多线程读取数据
	 */
	read() {
		console.log('dsfsd')
		let setTimeCount = 0;
		clearInterval(setIntervalId);
		setIntervalId = setInterval(()=> {
			setTimeCount++;
			if(this.state.readThreadState) {
				let t = new Date().getTime();
				//心跳检测
				if(setTimeCount % 20 == 0) {
					try {
						btOutStream.write([0b00]);
					} catch(e) {
						this.state.readThreadState = false;
						this.options.connExceptionCallback && this.options.connExceptionCallback(e);
					}
				}
				let dataArr = [];
				while(invoke(btInStream, "available") !== 0) {
					let data = invoke(btInStream, "read");
					dataArr.push(data);
					let ct = new Date().getTime();
					if(ct - t > 20) {
						break;
					}
				}
				if(dataArr.length > 0) {
					this.options.readDataCallback && this.options.readDataCallback(dataArr);
				}
			}
		}, 40);
	},
	/**
	 * 发送数据
	 * @param {String} dataStr
	 * @return {Boolean}
	 */
	sendData(dataStr) {
		if(!btOutStream) {
			this.shortToast("创建输出流失败！");
			return;
		}
		let bytes = invoke(dataStr, 'getBytes', 'gbk');
		try {
			btOutStream.write(bytes);
		} catch(e) {
			return false;
		}
		return true;
	},
	sendByteData(byteData) {
		if(!btOutStream) {
			this.shortToast("创建输出流失败！");
			return;
		}
		try {
			btOutStream.write(byteData);
		} catch(e) {
			return false;
		}
		return true;
	}
}

module.exports = blueToothTool