"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.presetsZosung = exports.tzZosung = exports.fzZosung = exports.zosungExtend = void 0;
const zigbee_herdsman_1 = require("zigbee-herdsman");
const m = __importStar(require("../lib/modernExtend"));
const exposes = __importStar(require("./exposes"));
const logger_1 = require("./logger");
const globalStore = __importStar(require("./store"));
const NS = "zhc:zosung";
const ea = exposes.access;
const e = exposes.presets;
exports.zosungExtend = {
    addZosungIRTransmitCluster: () => m.deviceAddCustomCluster("zosungIRTransmit", {
        name: "zosungIRTransmit",
        ID: 0xed00,
        attributes: {},
        commands: {
            zosungSendIRCode00: {
                name: "zosungSendIRCode00",
                ID: 0x00,
                parameters: [
                    { name: "seq", type: zigbee_herdsman_1.Zcl.DataType.UINT16, max: 0xffff },
                    { name: "length", type: zigbee_herdsman_1.Zcl.DataType.UINT32, max: 0xffffffff },
                    { name: "unk1", type: zigbee_herdsman_1.Zcl.DataType.UINT32, max: 0xffffffff },
                    { name: "unk2", type: zigbee_herdsman_1.Zcl.DataType.UINT16, max: 0xffff },
                    { name: "unk3", type: zigbee_herdsman_1.Zcl.DataType.UINT8, max: 0xff },
                    { name: "cmd", type: zigbee_herdsman_1.Zcl.DataType.UINT8, max: 0xff },
                    { name: "unk4", type: zigbee_herdsman_1.Zcl.DataType.UINT16, max: 0xffff },
                ],
            },
            zosungSendIRCode01: {
                name: "zosungSendIRCode01",
                ID: 0x01,
                parameters: [
                    { name: "zero", type: zigbee_herdsman_1.Zcl.DataType.UINT8, max: 0xff },
                    { name: "seq", type: zigbee_herdsman_1.Zcl.DataType.UINT16, max: 0xffff },
                    { name: "length", type: zigbee_herdsman_1.Zcl.DataType.UINT32, max: 0xffffffff },
                    { name: "unk1", type: zigbee_herdsman_1.Zcl.DataType.UINT32, max: 0xffffffff },
                    { name: "unk2", type: zigbee_herdsman_1.Zcl.DataType.UINT16, max: 0xffff },
                    { name: "unk3", type: zigbee_herdsman_1.Zcl.DataType.UINT8, max: 0xff },
                    { name: "cmd", type: zigbee_herdsman_1.Zcl.DataType.UINT8, max: 0xff },
                    { name: "unk4", type: zigbee_herdsman_1.Zcl.DataType.UINT16, max: 0xffff },
                ],
            },
            zosungSendIRCode02: {
                name: "zosungSendIRCode02",
                ID: 0x02,
                parameters: [
                    { name: "seq", type: zigbee_herdsman_1.Zcl.DataType.UINT16, max: 0xffff },
                    { name: "position", type: zigbee_herdsman_1.Zcl.DataType.UINT32, max: 0xffffffff },
                    { name: "maxlen", type: zigbee_herdsman_1.Zcl.DataType.UINT8, max: 0xff },
                ],
            },
            zosungSendIRCode03: {
                name: "zosungSendIRCode03",
                ID: 0x03,
                parameters: [
                    { name: "zero", type: zigbee_herdsman_1.Zcl.DataType.UINT8, max: 0xff },
                    { name: "seq", type: zigbee_herdsman_1.Zcl.DataType.UINT16, max: 0xffff },
                    { name: "position", type: zigbee_herdsman_1.Zcl.DataType.UINT32, max: 0xffffffff },
                    { name: "msgpart", type: zigbee_herdsman_1.Zcl.DataType.OCTET_STR },
                    { name: "msgpartcrc", type: zigbee_herdsman_1.Zcl.DataType.UINT8, max: 0xff },
                ],
            },
            zosungSendIRCode04: {
                name: "zosungSendIRCode04",
                ID: 0x04,
                parameters: [
                    { name: "zero0", type: zigbee_herdsman_1.Zcl.DataType.UINT8, max: 0xff },
                    { name: "seq", type: zigbee_herdsman_1.Zcl.DataType.UINT16, max: 0xffff },
                    { name: "zero1", type: zigbee_herdsman_1.Zcl.DataType.UINT16, max: 0xffff },
                ],
            },
            zosungSendIRCode05: {
                name: "zosungSendIRCode05",
                ID: 0x05,
                parameters: [
                    { name: "seq", type: zigbee_herdsman_1.Zcl.DataType.UINT16, max: 0xffff },
                    { name: "zero", type: zigbee_herdsman_1.Zcl.DataType.UINT16, max: 0xffff },
                ],
            },
        },
        commandsResponse: {
            zosungSendIRCode03Resp: {
                name: "zosungSendIRCode03Resp",
                ID: 0x03,
                parameters: [
                    { name: "zero", type: zigbee_herdsman_1.Zcl.DataType.UINT8, max: 0xff },
                    { name: "seq", type: zigbee_herdsman_1.Zcl.DataType.UINT16, max: 0xffff },
                    { name: "position", type: zigbee_herdsman_1.Zcl.DataType.UINT32, max: 0xffffffff },
                    { name: "msgpart", type: zigbee_herdsman_1.Zcl.DataType.OCTET_STR },
                    { name: "msgpartcrc", type: zigbee_herdsman_1.Zcl.DataType.UINT8, max: 0xff },
                ],
            },
            zosungSendIRCode05Resp: {
                name: "zosungSendIRCode05Resp",
                ID: 0x05,
                parameters: [
                    { name: "seq", type: zigbee_herdsman_1.Zcl.DataType.UINT16, max: 0xffff },
                    { name: "zero", type: zigbee_herdsman_1.Zcl.DataType.UINT16, max: 0xffff },
                ],
            },
        },
    }),
    addZosungIRControlCluster: () => m.deviceAddCustomCluster("zosungIRControl", {
        name: "zosungIRControl",
        ID: 0xe004,
        attributes: {},
        commands: {
            zosungControlIRCommand00: {
                name: "zosungControlIRCommand00",
                ID: 0x00,
                parameters: [
                    // JSON string with a command.
                    { name: "data", type: zigbee_herdsman_1.Zcl.BuffaloZclDataType.BUFFER },
                ],
            },
        },
        commandsResponse: {},
    }),
};
function nextSeq(entity) {
    return (globalStore.getValue(entity, "seq", -1) + 1) % 0x10000;
}
function messagesGet(entity, seq) {
    const info = globalStore.getValue(entity, "irMessageInfo");
    const expected = info?.seq || 0;
    if (expected !== seq) {
        throw new Error(`Unexpected sequence value (expected: ${expected} current: ${seq}).`);
    }
    if (info) {
        return info.data;
    }
    logger_1.logger.debug("Ignoring, no message send yet", NS);
}
function messagesSet(entity, seq, data) {
    globalStore.putValue(entity, "irMessageInfo", { seq: seq, data: data });
}
function messagesClear(entity, seq) {
    const info = globalStore.getValue(entity, "irMessageInfo");
    const expected = info?.seq || 0;
    if (expected !== seq) {
        throw new Error(`Unexpected sequence value (expected: ${expected} current: ${seq}).`);
    }
    globalStore.clearValue(entity, "irMessageInfo");
}
function calcArrayCrc(values) {
    return Array.from(values).reduce((a, b) => a + b, 0) % 0x100;
}
function calcStringCrc(str) {
    return (str
        .split("")
        .map((x) => x.charCodeAt(0))
        .reduce((a, b) => a + b, 0) % 0x100);
}
exports.fzZosung = {
    zosung_send_ir_code_01: {
        cluster: "zosungIRTransmit",
        type: ["commandZosungSendIRCode01"],
        convert: (model, msg, publish, options, meta) => {
            logger_1.logger.debug(`"IR-Message-Code01" received (msg:${JSON.stringify(msg.data)})`, NS);
            const seq = msg.data.seq;
            const irMsg = messagesGet(msg.endpoint, seq);
            if (irMsg) {
                logger_1.logger.debug(`IRCode to send: ${JSON.stringify(irMsg)} (seq:${seq})`, NS);
            }
        },
    },
    zosung_send_ir_code_02: {
        cluster: "zosungIRTransmit",
        type: ["commandZosungSendIRCode02"],
        convert: async (model, msg, publish, options, meta) => {
            logger_1.logger.debug(`"IR-Message-Code02" received (msg:${JSON.stringify(msg.data)})`, NS);
            const seq = msg.data.seq;
            const position = msg.data.position;
            const irMsg = messagesGet(msg.endpoint, seq);
            if (irMsg) {
                const part = irMsg.substring(position, position + 0x32);
                const sum = calcStringCrc(part);
                await msg.endpoint.command("zosungIRTransmit", "zosungSendIRCode03", {
                    zero: 0,
                    seq: seq,
                    position: position,
                    msgpart: Buffer.from(part),
                    msgpartcrc: sum,
                }, { disableDefaultResponse: true });
                logger_1.logger.debug(`Sent IRCode part: ${part} (sum: ${sum}, seq:${seq})`, NS);
            }
        },
    },
    zosung_send_ir_code_04: {
        cluster: "zosungIRTransmit",
        type: ["commandZosungSendIRCode04"],
        convert: async (model, msg, publish, options, meta) => {
            logger_1.logger.debug(`"IR-Message-Code04" received (msg:${JSON.stringify(msg.data)})`, NS);
            const seq = msg.data.seq;
            await msg.endpoint.command("zosungIRTransmit", "zosungSendIRCode05", {
                seq: seq,
                zero: 0,
            }, { disableDefaultResponse: true });
            messagesClear(msg.endpoint, seq);
            logger_1.logger.debug(`IRCode has been successfully sent. (seq:${seq})`, NS);
        },
    },
    zosung_send_ir_code_00: {
        cluster: "zosungIRTransmit",
        type: ["commandZosungSendIRCode00"],
        convert: async (model, msg, publish, options, meta) => {
            logger_1.logger.debug(`"IR-Message-Code00" received (msg:${JSON.stringify(msg.data)})`, NS);
            const seq = msg.data.seq;
            const length = msg.data.length;
            messagesSet(msg.endpoint, seq, { position: 0, buf: Buffer.alloc(length) });
            await msg.endpoint.command("zosungIRTransmit", "zosungSendIRCode01", {
                zero: 0,
                seq: seq,
                length: length,
                unk1: msg.data.unk1,
                unk2: msg.data.unk2,
                unk3: msg.data.unk3,
                cmd: msg.data.cmd,
                unk4: msg.data.unk4,
            }, { disableDefaultResponse: true });
            logger_1.logger.debug(`"IR-Message-Code00" response sent.`, NS);
            await msg.endpoint.command("zosungIRTransmit", "zosungSendIRCode02", {
                seq: msg.data.seq,
                position: 0,
                maxlen: 0x38,
            }, { disableDefaultResponse: true });
            logger_1.logger.debug(`"IR-Message-Code00" transfer started.`, NS);
        },
    },
    zosung_send_ir_code_03: {
        cluster: "zosungIRTransmit",
        type: ["commandZosungSendIRCode03Resp"],
        convert: async (model, msg, publish, options, meta) => {
            logger_1.logger.debug(`"IR-Message-Code03" received (msg:${JSON.stringify(msg.data)})`, NS);
            const seq = msg.data.seq;
            const rcv = messagesGet(msg.endpoint, seq);
            if (rcv) {
                if (rcv.position === msg.data.position) {
                    const rcvMsgPart = msg.data.msgpart;
                    const sum = calcArrayCrc(rcvMsgPart);
                    const expectedPartCrc = msg.data.msgpartcrc;
                    if (sum === expectedPartCrc) {
                        const position = rcvMsgPart.copy(rcv.buf, rcv.position);
                        rcv.position += position;
                        if (rcv.position < rcv.buf.length) {
                            await msg.endpoint.command("zosungIRTransmit", "zosungSendIRCode02", {
                                seq: seq,
                                position: rcv.position,
                                maxlen: 0x38,
                            }, { disableDefaultResponse: true });
                        }
                        else {
                            await msg.endpoint.command("zosungIRTransmit", "zosungSendIRCode04", {
                                zero0: 0,
                                seq: seq,
                                zero1: 0,
                            }, { disableDefaultResponse: true });
                        }
                        logger_1.logger.debug(`${rcvMsgPart.length} bytes received.`, NS);
                    }
                    else {
                        logger_1.logger.error(`Invalid msg part CRC: ${sum} expecting: ${expectedPartCrc}.`, NS);
                    }
                }
                else {
                    logger_1.logger.error(`Unexpected IR code position: ${JSON.stringify(msg.data)}, expecting: ${rcv.position}.`, NS);
                }
            }
        },
    },
    zosung_send_ir_code_05: {
        cluster: "zosungIRTransmit",
        type: ["commandZosungSendIRCode05Resp"],
        convert: async (model, msg, publish, options, meta) => {
            logger_1.logger.debug(`"IR-Message-Code05" received (msg:${JSON.stringify(msg.data)})`, NS);
            const seq = msg.data.seq;
            const rcv = messagesGet(msg.endpoint, seq);
            if (rcv) {
                const learnedIRCode = rcv.buf.toString("base64");
                logger_1.logger.debug(`Received: ${learnedIRCode}`, NS);
                messagesClear(msg.endpoint, seq);
                await msg.endpoint.command("zosungIRControl", "zosungControlIRCommand00", {
                    data: Buffer.from(JSON.stringify({ study: 1 })),
                }, { disableDefaultResponse: true });
                return {
                    learned_ir_code: learnedIRCode,
                };
            }
        },
    },
};
exports.tzZosung = {
    zosung_ir_code_to_send: {
        key: ["ir_code_to_send"],
        convertSet: async (entity, key, value, meta) => {
            if (!value) {
                logger_1.logger.error("There is no IR code to send", NS);
                return;
            }
            const irMsg = JSON.stringify({
                key_num: 1,
                delay: 300,
                key1: {
                    num: 1,
                    freq: 38000,
                    type: 1,
                    key_code: value,
                },
            });
            logger_1.logger.debug(`Sending IR code: ${JSON.stringify(value)}`, NS);
            const seq = nextSeq(entity);
            messagesSet(entity, seq, irMsg);
            await entity.command("zosungIRTransmit", "zosungSendIRCode00", {
                seq: seq,
                length: irMsg.length,
                unk1: 0x00000000,
                unk2: 0xe004,
                unk3: 0x01,
                cmd: 0x02,
                unk4: 0x0000,
            }, { disableDefaultResponse: true });
            logger_1.logger.debug("Sending IR code initiated.", NS);
        },
    },
    zosung_learn_ir_code: {
        key: ["learn_ir_code"],
        convertSet: async (entity, key, value, meta) => {
            logger_1.logger.debug("Starting IR Code Learning...", NS);
            await entity.command("zosungIRControl", "zosungControlIRCommand00", {
                data: Buffer.from(JSON.stringify({ study: 0 })),
            }, { disableDefaultResponse: true });
            logger_1.logger.debug("IR Code Learning started.", NS);
        },
    },
};
exports.presetsZosung = {
    learn_ir_code: () => e.binary("learn_ir_code", ea.SET, "ON", "OFF").withDescription("Turn on to learn new IR code"),
    learned_ir_code: () => e.text("learned_ir_code", ea.STATE).withDescription("The IR code learned by device"),
    ir_code_to_send: () => e.text("ir_code_to_send", ea.SET).withDescription("The IR code to send by device"),
};
//# sourceMappingURL=zosung.js.map