const readServiceID = '0000FFE0-0000-1000-8000-00805F9B34FB';
const readID = '0000FFE4-0000-1000-8000-00805F9B34FB';
const writeServiceID = '0000FFE5-0000-1000-8000-00805F9B34FB';
const writeID = '0000FFE9-0000-1000-8000-00805F9B34FB';
var readPart = '';
function acceptDevice(device) {
    return device.btid ? true : false;
}
function isDevice(device, data) {
    const advertisData = new Uint8Array(data.advertisData);
    const mac = device.btid
        .split('')
        .map((p, i) => parseInt(p + device.btid[i + 1], 16))
        .filter((p, i) => i % 2 == 0);
    if (advertisData.slice(0, 2).toString() == [82, 83].toString() && advertisData.slice(4, 10).toString() == mac.toString()) {
        return true;
    }
    return false;
}
function readDataBP00(value, data) {
    if (value.split('HSO').length == 2) {
        data.imei = value.split('HSO')[0];
        value = value.split('HSO')[1];
        while (value != '') {
            switch (value[0]) {
                case 'P':
                    data.quantity = parseInt(value.slice(1, 3));
                    value = value.slice(3, value.length);
                    break;
                case 'S':
                    data.gpscount = parseInt(value.slice(1, 3), 16);
                    value = value.slice(3, value.length);
                    break;
                case 'G':
                    data.gsmlevel = parseInt(value.slice(1, 3), 16);
                    value = value.slice(3, value.length);
                    break;
                case 'T':
                    data.temp = parseInt(value.slice(1, 5), 16) < 32768 ? parseInt(value.slice(1, 5), 16) : parseInt(value.slice(1, 5), 16) - 65536;
                    value = value.slice(5, value.length);
                    break;
                case 'C':
                    data.cycle = parseInt(value.slice(1, 5), 16);
                    value = value.slice(5, value.length);
                    break;
                case 'B':
                    var state = parseInt(value.slice(1, 3), 16);
                    data.lowTempProtectState = (state >> 0) & 1;
                    data.highTempProtectState = (state >> 1) & 1;
                    data.dischargeProtectState = (state >> 2) & 1;
                    data.chargeProtectState = (state >> 3) & 1;
                    data.lowVoltageState = (state >> 4) & 1;
                    data.chargeState = (state >> 5) & 3;
                    data.oilState = (state >> 7) & false ? 1 : 0;
                    value = value.slice(3, value.length);
                    break;
                case 'X':
                    var state = parseInt(value.slice(1, 3), 16);
                    data.autoProtectState = (state >> 0) & 1;
                    data.elecState = (state >> 1) & false ? 1 : 0;
                    data.factoryType = state >> 2;
                    value = value.slice(3, value.length);
                    break;
                default:
                    if (['P', 'S', 'G', 'T', 'C', 'B', 'X'].indexOf(value[3]) == -1) {
                        //data.voltage = parseInt(value.slice(0, 4), 16) / 100
                        value = value.slice(4, value.length);
                    } else {
                        //data.voltage = parseInt(value.slice(0, 3), 16) / 100
                        value = value.slice(3, value.length);
                    }
            }
        }
        console.log(data);
        return data;
    }
    return false;
}
function readDataBS50(value, data) {
    const length = parseInt(value.slice(0, 4), 16);
    value = value.slice(4, value.length);
    if (value.length == length * 2) {
        console.log(value);
        return BMSReply(
            value
                .split('')
                .map((p, i) => parseInt(p + value[i + 1], 16))
                .filter((p, i) => i % 2 == 0),
            data
        );
    }
    return false;
}
function BMSReply(value, data) {
    if (value[0] == 78 && value[1] == 87) {
        //value = value.slice(2, value.length)
        const length = value[2] * 256 + value[3];
        if (value.length == length + 2) {
            data.bmsid = value
                .slice(4, 8)
                .map((p) => ('00' + p.toString(16)).substr(p.toString(16).length))
                .join('');
            if (
                value[8] == 6 &&
                value[value.length - 5] == 104 &&
                value.slice(0, value.length - 4).reduce((p, c) => p + c) == value[value.length - 2] * 256 + value[value.length - 1]
            ) {
                value = value.slice(11, value.length - 9);
                while (value.length != 0) {
                    switch (value[0]) {
                        case 121:
                            const voltageLength = parseInt(value[1] / 3);
                            data.voltageList = Array(voltageLength);
                            let maxVoltage = -1;
                            let minVoltage = 99999;
                            let sumVoltage = 0;
                            for (var i = 0; i < voltageLength; i++) {
                                let _v = Math.round(value[i * 3 + 3] * 256 + value[i * 3 + 4]) / 1000;
                                console.log('xxxxx');
                                console.log(value[i * 3 + 2] - 1);
                                data.voltageList[value[i * 3 + 2] - 1] = _v;
                                sumVoltage += _v;
                                if (_v > maxVoltage) {
                                    maxVoltage = _v;
                                }
                                if (_v < minVoltage) {
                                    minVoltage = _v;
                                }
                            }
                            data.maxVoltage = maxVoltage;
                            data.minVoltage = minVoltage;
                            data.sumVoltage = sumVoltage;
                            value = value.slice(voltageLength * 3 + 2, value.length);
                            break;
                        case 128:
                            data.powerMOSTemp = value[1] * 256 + value[2];
                            if (data.powerMOSTemp > 100) {
                                data.powerMOSTemp = 100 - data.powerMOSTemp;
                            }
                            value = value.slice(3, value.length);
                            break;
                        case 129:
                            data.batteryChamberTemp = value[1] * 256 + value[2];
                            if (data.batteryChamberTemp > 100) {
                                data.batteryChamberTemp = 100 - data.batteryChamberTemp;
                            }
                            value = value.slice(3, value.length);
                            break;
                        case 130:
                            data.temp = value[1] * 256 + value[2];
                            if (data.temp > 100) {
                                data.temp = 100 - data.temp;
                            }
                            value = value.slice(3, value.length);
                            break;
                        case 131:
                            data.voltage = Math.round(value[1] * 256 + value[2]) / 100;
                            value = value.slice(3, value.length);
                            break;
                        case 132:
                            data.chargeState = 0;
                            let _value = value[1] * 256 + value[2];
                            if (_value > 10000) {
                                data.current = (_value - 10000) * 0.01 * -1;
                                data.chargeState = 2;
                            } else if (_value < 10000) {
                                data.current = (10000 - _value) * 0.01;
                                data.chargeState = 1;
                            }
                            value = value.slice(3, value.length);
                            break;
                        case 133:
                            data.quantity = value[1];
                            data.soc = value[1];
                            value = value.slice(2, value.length);
                            break;
                        case 134:
                            data.tempCount = value[1];
                            value = value.slice(2, value.length);
                            break;
                        case 135:
                            data.cycle = value[1] * 256 + value[2];
                            value = value.slice(3, value.length);
                            break;
                        case 137:
                            data.totalCirculatingCapacity = value[1] * 16777216 + value[2] * 65536 + value[3] * 256 + value[4];
                            value = value.slice(5, value.length);
                            break;
                        case 138:
                            data.count = value[1] * 256 + value[2];
                            value = value.slice(3, value.length);
                            break;
                        case 139:
                            data.alarmState = [];
                            if (((value[2] >> 0) & 1) == 1) {
                                data.alarmState.push('低容量报警');
                            }
                            if (((value[2] >> 1) & 1) == 1) {
                                data.alarmState.push('MOS管超温报警');
                            }
                            if (((value[2] >> 2) & 1) == 1) {
                                data.alarmState.push('充电过压报警');
                            }
                            if (((value[2] >> 3) & 1) == 1) {
                                data.alarmState.push('放电欠压报警');
                            }
                            if (((value[2] >> 4) & 1) == 1) {
                                data.alarmState.push('电池超温报警');
                            }
                            if (((value[2] >> 5) & 1) == 1) {
                                data.alarmState.push('充电过流报警');
                            }
                            if (((value[2] >> 6) & 1) == 1) {
                                data.alarmState.push('放电过流报警');
                            }
                            if (((value[2] >> 7) & 1) == 1) {
                                data.alarmState.push('电芯压差报警');
                            }
                            if (((value[1] >> 0) & 1) == 1) {
                                data.alarmState.push('电池箱内超温报警');
                            }
                            if (((value[1] >> 1) & 1) == 1) {
                                data.alarmState.push('电池低温报警');
                            }
                            if (((value[1] >> 2) & 1) == 1) {
                                data.alarmState.push('单体过压报警');
                            }
                            if (((value[1] >> 3) & 1) == 1) {
                                data.alarmState.push('单体欠压报警');
                            }
                            if (((value[1] >> 4) & 1) == 1) {
                                data.alarmState.push('309_A保护');
                            }
                            if (((value[1] >> 5) & 1) == 1) {
                                data.alarmState.push('309_B保护');
                            }
                            value = value.slice(3, value.length);
                            break;
                        case 140:
                            let _tmp = (value[1] << 8) | value[2];
                            // data.chargeProtectState = (value[2] >> 0 & 1)
                            // data.dischargeProtectState = (value[2] >> 1 & 1)
                            // data.equilibrium = (value[2] >> 2 & 1)
                            // data.disconnectState = (value[2] >> 3 & 1)
                            data.chargeProtectState = (_tmp & 1) == 0 ? 0 : 1;
                            data.dischargeProtectState = (_tmp & 2) == 0 ? 0 : 1;
                            data.equilibrium = (_tmp & 4) == 0 ? 0 : 1;
                            data.disconnectState = (_tmp & 8) == 0 ? 0 : 1;
                            value = value.slice(3, value.length);
                            //console.log(value[1] + "  " . value[2] + "  " + _tmp + "  ;" + data.equilibrium)
                            break;
                        case 142:
                            value = value.slice(3, value.length);
                            break;
                        case 143:
                            value = value.slice(3, value.length);
                            break;
                        case 144:
                            value = value.slice(3, value.length);
                            break;
                        case 145:
                        case 146:
                        case 147:
                        case 148:
                        case 149:
                        case 150:
                        case 151:
                        case 152:
                        case 153:
                        case 154:
                        case 155:
                        case 156:
                            value = value.slice(3, value.length);
                            break;
                        case 157:
                            value = value.slice(2, value.length);
                            break;
                        case 158:
                        case 159:
                        case 160:
                        case 161:
                        case 162:
                        case 163:
                        case 164:
                        case 165:
                        case 166:
                        case 167:
                        case 168:
                            value = value.slice(3, value.length);
                            break;
                        case 169:
                            value = value.slice(2, value.length);
                            break;
                        case 170:
                            // 电池容量
                            data.capacity = (value[1] << 24) | (value[2] << 16) | (value[3] << 8) | value[4];
                            value = value.slice(5, value.length);
                            break;
                        case 171:
                        case 172:
                            value = value.slice(2, value.length);
                            break;
                        case 173:
                            value = value.slice(3, value.length);
                            break;
                        case 174:
                        case 175:
                            value = value.slice(2, value.length);
                            break;
                        case 176:
                            value = value.slice(3, value.length);
                            break;
                        case 177:
                            value = value.slice(2, value.length);
                            break;
                        case 178:
                            value = value.slice(11, value.length);
                            break;
                        case 179:
                            value = value.slice(2, value.length);
                            break;
                        case 180:
                            value = value.slice(9, value.length);
                            break;
                        case 181:
                            value = value.slice(5, value.length);
                            break;
                        case 182:
                            value = value.slice(5, value.length);
                            break;
                        case 183:
                            // 软件版本号 15bit
                            data.firmware = '';
                            for (let i = 1; i <= 15; i++) {
                                let _value = 33;
                                let hx = value[i];
                                if (hx >= 33 && hx <= 126) {
                                    _value = hx;
                                }
                                data.firmware += String.fromCharCode(_value);
                            }
                            value = value.slice(16, value.length);
                            break;
                        case 184:
                            value = value.slice(2, value.length);
                            break;
                        case 185:
                            value = value.slice(5, value.length);
                            break;
                        case 186:
                            value = value.slice(25, value.length);
                            break;
                        default:
                            value = [];
                    }
                }
            }
            return data;
        }
    }
    return false;
}
function readData(device, value, data) {
    value = Array.from(new Int8Array(value))
        .map((p) => String.fromCharCode(p))
        .join('');
    console.log(value);
    if (value[value.length - 1] == ')') {
        value = readPart.concat(value);
        readPart = '';
    } else if (value[0] == '(') {
        readPart = value;
    } else {
        readPart = readPart.concat(value);
    }
    console.log(value);
    if (value[0] == '(' && value[value.length - 1] == ')') {
        value = value.slice(1, value.length - 1);
        if (value.slice(0, 12) == device.mac_id) {
            value = value.slice(12, value.length);
            switch (value.slice(0, 4)) {
                case 'BP00':
                    return readDataBP00(value.slice(4, value.length), data);
                case 'BS50':
                    return readDataBS50(value.slice(4, value.length), data);
            }
        }
    }
    return false;
}

/**
 * cmd: 命令字 02:写
 */
function BMSCommand(data, cmd, type = 0) {
    // 帧来源: 01
    // 传输类型: 00
    const length = data.length + 18;
    var data = [78, 87, parseInt(length / 256), parseInt(length % 256), 0, 0, 0, 0, cmd, 1, type].concat(data).concat([0, 0, 0, 0, 104]);
    const sum = data.reduce((p, c) => p + c);
    data.push(parseInt(sum / 16777216));
    data.push(parseInt((sum % 16777216) / 65536));
    data.push(parseInt((sum % 65536) / 256));
    data.push(parseInt(sum % 256));
    console.log('222222');
    console.log(data);
    return data;
}
function BMSRead() {
    return BMSCommand([0], 6, 0);
}
function BMSTurnOn() {
    return BMSCommand([172, 1], 2, 1);
}
function BMSTurnOff() {
    return BMSCommand([172, 0], 2, 1);
}
function bmsChargingMOS(value) {
    return BMSCommand([171, value], 2, 0);
}
function bmsDischargeMOS(value, device) {
    return BMSCommand([172, value], 2, 0);
}
function sendData(device, cmd, data = []) {
    return (
        '(' +
        device.mac_id +
        cmd +
        data
            .map((p) => ('00' + p.toString(16)).substr(p.toString(16).length))
            .join('')
            .toUpperCase() +
        ')'
    )
        .split('')
        .map((p) => p.charCodeAt(0));
}
function sendDataAE00(device, data) {
    return sendData(device, 'AE00', [data.length % 256, parseInt(data.length / 256)].concat(data));
}
function stateUpdate(device, deviceId) {
    return [sendData(device, 'AU20'), sendDataAE00(device, BMSRead())];
}
function turnOn(device, deviceId) {
    return [sendDataAE00(device, BMSTurnOn())];
}
function turnOff(device, deviceId) {
    return [sendDataAE00(device, BMSTurnOff())];
}
function bmsInfo(device, deviceId, info) {
    console.log('--------');
    console.log(info);
    return false;
}
function bmsSet(device) {
    return false;
}
module.exports = {
    readServiceID: readServiceID,
    readID: readID,
    writeServiceID: writeServiceID,
    writeID: writeID,
    acceptDevice: acceptDevice,
    isDevice: isDevice,
    readData: readData,
    stateUpdate: stateUpdate,
    turnOn: turnOn,
    turnOff: turnOff,
    bmsInfo: bmsInfo,
    bmsSet: bmsSet,
    BMSCommand: BMSCommand,
    BMSRead: BMSRead,
    BMSTurnOn: BMSTurnOn,
    BMSTurnOff: BMSTurnOff,
    BMSReply: BMSReply,
    bmsChargingMOS: bmsChargingMOS,
    bmsDischargeMOS: bmsDischargeMOS
};
