import errToString from "./error";
var util = require('../util');
const app =getApp()

let PRINT_SHOW = true //是否开启蓝牙调试
let SYSTEM_INFO = {}
let MTU_SIZE = 512

function toPlatformString(systemInfo, str) {
    if (systemInfo.platform == 'android')
        return str.toLowerCase();
    else if (systemInfo.platform == 'ios')
        return str.toUpperCase();
    else
        return str;
}

function _openAdapter() {

    print(`准备初始化蓝牙适配器...`);

    wx.getSystemInfo({
        success: function (res) {
            print(`model: ${res.model}`);
            print(`pixelRatio: ${res.pixelRatio}`);
            print(`windowWidth: ${res.windowWidth}`);
            print(`windowHeight: ${res.windowHeight}`);
            print(`language: ${res.language}`);
            print(`version: ${res.version}`);
            print(`platform: ${res.platform}`);
            print(`environment: ${res.environment}`);
            SYSTEM_INFO = res;
        }
    })

    return wx.openBluetoothAdapter().then(
        (res) => {
            print(`✔ 适配器初始化成功！`);
            return [null, res]
        },
        (err) => {
            print(`✘ 初始化失败！${errToString(err)}`);
            return [errToString(err), null]
        }
    );
}

/**
 * @param {Array<string>} services
 * @param { Int } interval
 */
function _startSearch() {
    print(`准备搜寻附近的蓝牙外围设备...`);
    return promisify(wx.startBluetoothDevicesDiscovery, {
        services: [this.serviceId], //如果填写了此UUID，那么只会搜索出含有这个UUID的设备
        allowDuplicatesKey: false,
        interval: 1000
    }).then(
        (res) => {
            print(`✔ 搜索成功!`);
            return [null, res]

        },
        (err) => {
            print(`✘ 搜索蓝牙设备失败！${errToString(err)}`);
            return [errToString(err), null]
        }
    );
}

/**
 *@param {Array<string>} devices
 *@deviceId 设备ID
 */
function _onBluetoothFound() {
    print(`监听搜寻新设备事件...`);
    return _onBluetoothFound_promise.call(this).then(res => { //_getBluetoothDevices_promise _onBluetoothFound_promise
        print(`✔ 设备 ${this.blename} 查找成功!`);
        return [null, res]
    }, err => {
        print(`✘ 设备 ${this.blename} 查找失败!`);
        return [errToString(err), null]

    })
}

/**
 * @param {Array} devices 查找到设备数组
 * @param {int} count 计数器-嗅探2次
 */
function _onBluetoothFound_promise() {
    let devices = []
    let count = 0
    return new Promise((resolve, reject) => {
        wx.onBluetoothDeviceFound(res => {
            devices.push(...res.devices)
            print(`已嗅探设备数：${devices.length}...`)
            print(`已嗅探设备信息：${JSON.stringify(devices)}`)
            count++
            print(`已嗅探次数：${count}`)
            //if (count > 1) 	
            if (devices.length > 0) {
                devices.forEach(element => {
                    if ((element.name && element.name == this.blename) || (element.localName && element.localName == this.blename)) {
                        this.deviceId = element.deviceId

                        print(`我的设备Mac：${this.deviceId}  `)
                        print(`我的设备名：${element.name}, ${element.localName}`)
                        resolve(res)
                    }
                });

            } else {
                reject('device not found')
            }


        }, err => {
            // reject(err)
        })
    })
}

/**
 *@param {Array<string>} devices
 *@deviceId 设备ID
 */
function _getBluetoothDevices() {
    print(`监听搜寻新设备事件...`);
    let devices = []
    return wx.getBluetoothDevices({
        success: function (res) {
            console.log(res)
            devices.push(res.devices)
            print(`已嗅探设备数：${res.devices.length}...`)
            print(`已嗅探设备信息：${JSON.stringify(res.devices)}`)
            if (devices.length > 0) {
                devices.forEach(element => {
                    if ((element.name && element.name == this.blename) || (element.localName && element.localName == this.blename)) {
                        this.deviceId = element.deviceId

                        print(`我的设备Mac：${this.deviceId}  `)
                        print(`我的设备名：${element.name}, ${element.localName}`)

                        print(`✔ 设备 ${this.blename} 查找成功!`);
                        return [null, res]
                    }
                });
            } else {
                return [`暂时没有嗅探到设备 ${this.blename}, 继续嗅探...`, null]
            }
        },
        fail: function (res) {
            print(`✘ 设备 ${this.blename} 查找失败!`);
            return [errToString(err), null]
        }
    })
}


function _getBluetoothDevices_1() {
    print(`监听搜寻新设备事件...`);
    return _getBluetoothDevices_promise.call(this).then(res => {
        print(`✔ 设备 ${this.blename} 查找成功!`);
        return [null, res]
    }, err => {
        print(`✘ 设备 ${this.blename} 查找失败!`);
        return [errToString(err), null]
    })
}

/**
 * @param {Array} devices 查找到设备数组
 * @param {int} count 计数器-嗅探2次
 */
function _getBluetoothDevices_promise() {
    let devices = []
    print(`1111`)
    return new Promise((resolve, reject) => {

        print(`2222`)

        wx.getBluetoothDevices(res => {

            print(`3333`)
            devices.push(...res.devices)
            print(`已嗅探设备数：${devices.length}...`)
            print(`已嗅探设备信息：${JSON.stringify(devices)}`)
            if (devices.length > 0) {
                devices.forEach(element => {
                    if ((element.name && element.name == this.blename) || (element.localName && element.localName == this.blename)) {
                        this.deviceId = element.deviceId

                        print(`我的设备Mac：${this.deviceId}  `)
                        print(`我的设备名：${element.name}, ${element.localName}`)

                        resolve(res)
                    }
                });

            }
            reject('device not found')

        }, err => {

            print(`4444`)

            reject(err)
        })
    })
}



function _stopSearchBluetooth() {
    print(`停止查找新设备...`);
    return wx.stopBluetoothDevicesDiscovery().then(
        (res) => {
            print(`✔ 停止查找设备成功！`);
            return [null, res]
        },
        (err) => {
            print(`✘ 停止查询设备失败！${errToString(err)}`);
            return [errToString(err), null]
        }
    );
}

function _connectBlue() {
    print(`准备连接设备...`);
    return promisify(wx.createBLEConnection, {
        deviceId: this.deviceId,
    }).then(
        (res) => {
            print(`✔ 连接蓝牙成功！`);
            return [null, res]
        },
        (err) => {
            print(`✘ 连接蓝牙失败！${errToString(err)}`);
            return [errToString(err), null]
        }
    );
}

function _setBLEMTU() {

    if (SYSTEM_INFO.platform != 'android') {
        print(`仅安卓手机需要设置MTU Size`);
        return ["仅安卓手机需要设置MTU Size", null];
    }

    print(`准备设置 MTU Size...`);

    return promisify(wx.setBLEMTU, {
        deviceId: this.deviceId,
        mtu: MTU_SIZE
    }).then(
        (res) => {

            //console.log("setBLEMTU success >> " + JSON.stringify(res))
            print(`✔ 设置MTU Size = ${MTU_SIZE} 成功！`);
            return [null, res]
        },
        (err) => {

            //console.log("setBLEMTU fail >> " + JSON.stringify(res))
            print(`✘ 设置MTU Size 失败！`);
            return [errToString(err), null]
        }
    );
}

function _closeBLEConnection() {
    print(`断开蓝牙连接...`)
    return promisify(wx.closeBLEConnection, {
        deviceId: this.deviceId,
    }).then(
        (res) => {
            print(`✔ 断开蓝牙成功！`);
            return [null, res]
        },
        (err) => {
            print(`✘ 断开蓝牙连接失败！${errToString(err)}`);
            return [errToString(err), null]
        }
    );
}

function _closeBLEAdapter() {
    print(`释放蓝牙适配器...`)
    return wx.closeBluetoothAdapter().then(res => {
        print(`✔ 释放适配器成功！`)
        getApp().globalData.bleStatus = ''
        return [null, res]
    }, err => {
        print(`✘ 释放适配器失败！${errToString(err)}`)
        return [errToString(err), null]
    })
}

function _getBLEServices() {
    print(`获取蓝牙设备所有服务...`)
    return promisify(wx.getBLEDeviceServices, {
        deviceId: this.deviceId
    }).then(res => {
        print(`✔ 获取service成功！`)
        console.log('services UUID:\n', JSON.stringify(res.services));
        for (var i = 0; i < res.services.length; i++) {
            console.log("第" + (i + 1) + "个UUID:" + res.services[i].uuid + "\n")
        }
        return [null, res]
    }, err => {
        print(`✘ 获取service失败！${errToString(err)}`)
        return [errToString(err), null]
    })
}

function _getCharacteristics() {
    print(`开始获取特征值...`);
    return promisify(wx.getBLEDeviceCharacteristics, {
        deviceId: this.deviceId,
        serviceId: toPlatformString(SYSTEM_INFO, this.serviceId), //具有写、通知属性的服务uuid
    }).then(
        (res) => {
            print(`✔ 获取特征值成功！`);
            for (let i = 0; i < res.characteristics.length; i++) {
                let item = res.characteristics[i];
                if (item.properties.read) {
                    this.readCharacteristicId = item.uuid;
                    print(`readCharacteristicId:${item.uuid}`)
                }
                if (item.properties.write && !item.properties.read) {
                    this.writeCharacteristicId = item.uuid;
                    print(`writeCharacteristicId:${item.uuid}`)
                }
                if (item.properties.notify || item.properties.indicate) {
                    this.notifyCharacteristicId = item.uuid;
                    print(`notifyCharacteristicId:${item.uuid}`)
                }
            }
            return [null, res]
        },
        (err) => {
            print(`✘ 获取特征值失败！${errToString(err)}`);
            return [errToString(err), null]
        }
    );
}

// 订阅特征值
function _notifyBLECharacteristicValueChange() {
    return promisify(wx.notifyBLECharacteristicValueChange, {
        deviceId: this.deviceId,
        serviceId: toPlatformString(SYSTEM_INFO, this.serviceId),
        characteristicId: toPlatformString(SYSTEM_INFO, this.notifyCharacteristicId),
        state: true
    }).then(res => {
        wx.hideLoading()
        wx.showToast({
            title: "连接成功",
            duration: 2000,
            icon: "none"
        })
        print(`✔ 订阅notify成功！`)

        return [null, res]
    }, err => {
        wx.hideLoading()
        wx.showToast({
            title: `连接失败！${errToString(err)}`,
            duration: 2000,
            icon: "none"
        })
        print(`✘ 订阅notify失败！${errToString(err)}`)
        return [errToString(err), null]
    })
}

/**
 * 指令封装
 * @param {Array} data 
 */
function _sentOrder(cmd, payload, timestamp1) {
    print(`开始封装指令...`)
    console.log(payload)
    let data = payload
    let payloadLength = data.length;
    let length = 13 + payload.length
    let b = new Uint8Array(length);

    b[0] = 0x89;
    b[1] = 0x89;
    b[2] = cmd;
    console.log(timestamp1)
    // let timestamp = timestamp1 //new Date().getTime();

    //let ts = timestamp.toString(16)		
    // let t = util.IntToBytesLittleEndian(timestamp, 6)
    /*
    b[4] = (byte)((timestamp >> 40) & 0x00000000000000ff);
    b[5] = (byte)((timestamp >> 32) & 0x00000000000000ff);
    b[6] = (byte)((timestamp >> 24) & 0x00000000000000ff);
    b[7] = (byte)((timestamp >> 16) & 0x00000000000000ff);
    b[8] = (byte)((timestamp >> 8) & 0x00000000000000ff);
    b[9] = (byte)(timestamp  & 0x00000000000000ff);
    */
    let timestamp = timestamp1 //new Date().getTime();
    let t = new Uint8Array(6);
    for (let i = 0; i < 6; i++) {
        t[5 - i] = timestamp & 255;
        timestamp = timestamp >> 8;
    }
    console.log(t)
    b.set(t, 4)
    console.log(t)

    // b.set(t, 4)

    b[3] = b[9];

    b[10] = (payloadLength >> 8) & 0xff;
    b[11] = payloadLength & 0xff;
    let key = b[3];
    for (let i = 0; i < payloadLength; i++) {
        data[i] -= (payloadLength - i) ^ key;
        data[i] = (data[i] ^ (key ^ i));
    }

    b.set(data, 12)

    let xor = b[0];
    for (let i = 1; i < length - 1; i++)
        xor ^= b[i];

    b[length - 1] = xor;

    print(`✔ 封装成功! ${b}`)

    return b;
}


function _writeBLECharacteristicValue(data) {
    return promisify(wx.writeBLECharacteristicValue, {
        deviceId: this.deviceId,
        serviceId: toPlatformString(SYSTEM_INFO, this.serviceId),
        characteristicId: toPlatformString(SYSTEM_INFO, this.writeCharacteristicId),
        value: data,
    }).then(res => {
        print(`✔ 写入数据成功！`)
        return [null, res]
    }, err => {
        print(`✘ 写入数据失败！${errToString(err)}`)
        return [errToString(err), null]
    })
}

/**
 * 对微信接口的promise封装
 * @param {function} fn 
 * @param {object} args 
 */
function promisify(fn, args) {
    return new Promise((resolve, reject) => {
        fn({
            ...(args || {}),
            success: (res) => resolve(res),
            fail: (err) => reject(err),
        });
    });
}

/**
 * 对微信接口回调函数的封装
 * @param {function} fn 
 */
function promisify_callback(fn) {
    return new Promise((resolve, reject) => {
        fn(
            (res) => {
                resolve(res);
            },
            (rej) => {
                reject(rej);
            }
        );
    });
}

function print(str) {
    PRINT_SHOW ? console.log(str) : null;
}

export {
    print,
    _getCharacteristics,
    _connectBlue,
    _setBLEMTU,
    _getBLEServices,
    _closeBLEConnection,
    _closeBLEAdapter,
    _stopSearchBluetooth,
    _notifyBLECharacteristicValueChange,
    _onBluetoothFound,
    _getBluetoothDevices,
    _startSearch,
    _openAdapter,
    _sentOrder,
    _writeBLECharacteristicValue,
    promisify,
    promisify_callback,
};