// 设备命令
// TLV格式（16进制）
// 二进制协议使用 TLV (Type-Length-Value)编码格式。
// - Type：固定长度， 一字节。
// - Length：可变长度。 0 或 1 个字节。
// - Value：二进制数据。 长度由 Length 字段决定。 数据本身可以上数字或者字符串。

const EnumOpen = {
    close: 0,
    open: 1
};

const EnumConnectType = {
    bt: 0,
    ble: 1,
    upnp: 2,
    mqtt: 3
}

class BtCmd {
    // BtCmd._();
    constructor() { }

    // 获取版本号
    static queryVersion() {
        return this._build(CmdBase.queryVersion, [0x0]);
    }

    // 查询电量  电量值 0-9，0对应10%，9对应100%，10充电
    static queryKwh() {
        return this._build(CmdKwh.queryKwh, [0x0]);
    }

    // 查询耳机电量
    static queryKwhEarPhone() {
        return this._build(CmdEarPhone.queryEarPhoneKwh, [0x0]);
    }

    // 查询EQ音效
    static queryEQ() {
        return this._build(CmdEarPhone.queryEQ, [0x0]);
    }

    // 设置EQ音效
    static setEQ(list) {
        return this._build(CmdEarPhone.setEQ, list);
    }

    // B5耳机-低电耗模式
    static queryLowPower() {
        return this._build(CmdEarPhone.queryLowPower, [0x0]);
    }

    static setLowPowerMode(isOpen) {
        return this._build(CmdEarPhone.setLowPowerMode, [isOpen]);
    }

    // B5耳机-自定义操作手势
    static queryCtrlStatus() {
        return this._build(CmdEarPhone.queryCtrlStatus, [0x0]);
    }

    static setCtrlStatus(singleClick, doubleClick, longClick) {
        return this._build(CmdEarPhone.setCtrlStatus, [singleClick, doubleClick, longClick]);
    }

    // 查询低延时模式
    static queryLowDelayMode() {
        return this._build(CmdEarPhone.queryLowDelayMode, [0x0]);
    }

    // 低延时模式
    static setLowDelayMode(open, mode) {
        return this._build(CmdEarPhone.setLowDelayMode, [open, mode]);
    }

    // 低电量提示音
    static queryLowKwhWarningTone() {
        return this._build(CmdKwh.queryLowKwhWarningTone, [0x00]);
    }

    static setLowKwhWarningTone(isNotify) {
        return this._build(CmdKwh.setLowKwhWarningTone, isNotify ? [0x01] : [0x00]);
    }

    // 蓝牙自动播放
    static setAutoPlay(switchStatus) {
        return this._build(CmdBase.setAutoPlay, [switchStatus]);
    }

    static AutoPlay() {
        return this._build(CmdBase.getAutoPlay, [0x00]);
    }

    // 查询音量
    static queryVolume() {
        return this._build(CmdBase.queryVolume, [0x00]);
    }

    static setVolume(volume) {
        return this._build(CmdBase.setVolume, [volume]);
    }

    // 查询闹钟
    static queryAlarm() {
        return this._build(CmdRtc.queryAlarm, [0x00]);
    }

    // 设置闹钟
    static setAlarm(switchStatus, weekCycle, hour, minutes, channel = 1) {
        const weeks = CmdWeek.week2Cmd(weekCycle);
        return this._build(CmdRtc.setAlarm, [switchStatus, weeks, hour, minutes, channel]);
    }

    // 查询休眠
    static querySleep() {
        return this._build(CmdRtc.querySleep, [0x00]);
    }

    static querySleepAfterPlayPause() {
        return this._build(CmdRtc.querySleepAfterPlayPause, [0x00]);
    }

    static setSleepAfterPlayPause(time) {
        return this._build(CmdRtc.setSleepAfterPlayPause, [time]);
    }

    // 设置休眠
    static setSleep(switchStatus, hour, minutes) {
        return this._build(CmdRtc.setSleep, [switchStatus, hour, minutes]);
    }

    // 设置时间
    static setDevTime() {
        const now = new Date();
        const y = now.getFullYear();
        const year = Math.floor(y / 100);
        const _year = y % 100;
        const month = now.getMonth() + 1; // getMonth() 返回 0-11，所以需要加 1
        const day = now.getDate();
        const hour = now.getHours();
        const minutes = now.getMinutes();
        const seconds = now.getSeconds();

        // console.log(`setTime========${CmdRtc.setTime},${year},${_year},${month},${day},${hour},${minutes},${seconds}`);
        // console.log(`setTime======== 2,    ${CmdRtc.setTime}`);

        let cmd = this._build(0x50, [year, _year, month, day, hour, minutes, seconds]);
        console.log(`setTime========${cmd}`);
        return cmd;
    }

    // 查询时间
    static queryTime() {
        return this._build(CmdRtc.queryTime, [0x00]);
    }

    // 设置RGB
    static setRGB(r, g, b) {
        return this._build(CmdRgb.set, [r, g, b]);
    }

    // 查询RGB
    static queryRGB() {
        return this._build(CmdRgb.query, [0x0]);
    }

    static stringToUint8Array(str) {
        // 54 44 44 48 01 11 28 09 73 6d6172745f413246
        // const encoder = new TextEncoder();
        // const uint8Array = encoder.encode(str);
        // return uint8Array;
        return [0x73, 0x6d, 0x61, 0x72, 0x74, 0x5f, 0x41, 0x32, 0x46]
    }

    // 校验设备
    static checkDevice() {
        let secretKey = this.stringToUint8Array(CmdBase.secretKey)
        console.log(`checkDevice========${secretKey}`);
        return this._build(CmdBase.checkDevice, secretKey);
    }

    // 杰理语音开始回应
    static jlStartVoiceResponse() {
        return this._build(CmdVoice.jlStartVoiceResponse);
    }

    // 杰理语音结束回应
    static jlStopVoiceResponse() {
        return this._build(CmdVoice.jlStopVoiceResponse);
    }

    // 领芯语音
    static lxStartVoiceResponse() {
        return this._build(CmdVoice.lxStartVoiceResponse);
    }

    // 杰理语音结束回应
    static lxStopVoiceResponse() {
        return this._build(CmdVoice.lxStopVoiceResponse);
    }

    // b1开始语音回调
    static b1StartVoiceResponse() {
        const data = [0x04, 0x80, 0x01, 0x00, 0x02];
        return new Uint8Array(data);
    }

    // b1结束语音回调
    static b1StopVoiceResponse() {
        const data = [0x05, 0x80, 0x01, 0x00, 0x02];
        return new Uint8Array(data);
    }

    // 固定头部
    static get _header() {
        return [0x54, 0x44, 0x44, 0x48];
    }

    // 版本号
    static get _version() {
        return 0x01;
    }

    // 生成命令（固定头部+版本号+命令总长度+命令类型+）
    static _build(cmdType, otherCmd = [], isWriteChildCmdLength = true) {
        const cmd = [];

        // 固定头部
        cmd.push(...this._header);

        // 版本号
        cmd.push(this._version);

        // 命令类型
        cmd.push(cmdType);

        if (isWriteChildCmdLength) {
            // 子命令长度
            const childLength = this._int2Hex(otherCmd.length);
            cmd.push(childLength);
        }

        // 其他命令
        if (otherCmd.length > 0) {
            for (const element of otherCmd) {
                cmd.push(this._int2Hex(element));
            }
        }

        // 命令长度（位置在版本号之后）
        const length = cmd.length + 1;
        const l = this._int2Hex(length);
        cmd.splice(5, 0, l);
        return new Uint8Array(cmd);
    }

    // 打印cmd
    static printTLV(cmd, isSend = false) {
        let result = "";
        const key = isSend ? "发送" : "接收";
        if (isSend) {
            // console.log(`${key}原始-${cmd.toString()}`);
        }

        for (let i = 0; i < cmd.length; i++) {
            const cmdStr = `${this._int2HexString(cmd[i])}`.padStart(2, "0");
            result += cmdStr;
        }
        if (isSend) {
            mqttAddDebugCmd(`发送蓝牙指令：${cmd} \n ${result}`);
        }
        console.log(`${key}解析- [${result}]`);
    }

    static _int2Hex(value) {
        return value & 0xFF;
    }

    static _int2HexString(value) {
        return value.toString(16).toUpperCase();
    }
}

// 设备命令类型
const CmdBase = {
    secretKey: "smart_A2F",
    queryVersion: 0x30,
    checkDevice: 0x28,
    checkDeviceSuccess: 0x27,
    setAutoPlay: 0x24,
    getAutoPlay: 0x23,
    queryChannelAngle: 0x38,
    switchLed: 0x39,
    queryVolume: 0x32,
    setVolume: 0x33,
    newFlag: "MW-Mate X\\(4G_WIFI\\)|MW-2AX\\(WIFI-N\\)|MW-SR1\\(4G_WIFI\\)|MW-SR1\\(4G_WIFI_MEIZU01\\)",
    // volumeMax: (new RegExp(`^(${CmdBase.newFlag})$`, 'i').test(DeviceManager.instance.clientType || "")) ? 0x20 : 0xF,
    volumeMax: 15,

    parseVersion(version) {
        let ver;
        if (version <= 0) {
            ver = "1.0.0";
        } else {
            const split = version.toString().split("");
            if (split.length === 1) {
                split.unshift("0", "0");
            } else if (split.length === 2) {
                split.unshift("0");
            }
            ver = split.join(".");
        }
        console.log(`parseVersion======${version},,,,,,,${ver.toString()}`);
        return ver;
    }
};

// 耳机相关指令
const CmdEarPhone = {
    queryLowDelayMode: 0xb2,
    setLowDelayMode: 0xb3,
    queryEQ: 0xb4,
    setEQ: 0xb5,
    queryEarPhoneKwh: 0xb1,
    queryCtrlStatus: 0xB6,
    setCtrlStatus: 0xB7,
    queryLowPower: 0xB8,
    setLowPowerMode: 0xB9
};

// 时间相关
const CmdRtc = {
    setTime: 0x50,
    queryTime: 0x51,
    setAlarm: 0x52,
    queryAlarm: 0x54,
    setSleep: 0x56,
    querySleep: 0x57,
    setSleepAfterPlayPause: 0x5a,
    querySleepAfterPlayPause: 0x5b
};

// 设置设备颜色
const CmdRgb = {
    query: 0x80,
    set: 0x81
};

// 电量相关命令
const CmdKwh = {
    queryKwh: 0x22,
    setLowKwhWarningTone: 0x26,
    queryLowKwhWarningTone: 0x25
};

// 按键
const CmdKey = {
    previousSong: 0x0a,
    nextSong: 0x0b,
    previousChannel: 0x0c,
    nextChannel: 0x0d,
    type: 0x21,
    pressShort: 0x02,
    pressLongUp: 0x04,
    pressLong: 0x08,
    pressDouble: 0x09,
    next: 0x01,
    previous: 0x02,
    changeProgram: 0x03
};

// 语音
const CmdVoice = {
    startVoice: 0x01,
    jlStartVoice: 0x66,
    jlStopVoice: 0x68,
    jlStartVoiceResponse: 0x67,
    jlStopVoiceResponse: 0x69,
    jlReceiveVoiceData: 0x70,
    lxStartVoice: 0x71,
    lxStopVoice: 0x72,
    lxStartVoiceResponse: 0x40,
    lxStopVoiceResponse: 0x41,
    sjStartVoice: 0x23,
    sjStopVoice: 0x24
};

// 一周
const CmdWeek = {
    sunday: 0x01,
    monday: 0x02,
    tuesday: 0x04,
    wednesday: 0x08,
    thursday: 0x10,
    friday: 0x20,
    saturday: 0x40,
    weeks: [0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40],

    week2Cmd(weekCycle) {
        let result = 0;
        for (let i = 0; i < weekCycle.length; i++) {
            const item = weekCycle[i];
            if (item === EnumOpen.open) {
                result += this.weeks[i];
            }
        }
        return result;
    },

    cmd2Week(cmd) {
        const w = [0, 0, 0, 0, 0, 0, 0];
        for (let i = this.weeks.length - 1; i >= 0; i--) {
            const week = this.weeks[i];
            if (week <= cmd) {
                w[i] = EnumOpen.open;
                cmd -= week;
            }
        }
        return w;
    }
};

module.exports = {
    BtCmd,
    CmdBase,
    CmdEarPhone,
    CmdRtc,
    CmdRgb,
    CmdKwh,
    CmdKey,
    CmdVoice,
    CmdWeek
};
