"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.MatterOnOffDevice = exports.DeviceType = void 0;
const matter_node_js_1 = require("@project-chip/matter-node.js");
const device_1 = require("@project-chip/matter-node.js/device");
const util_1 = require("@project-chip/matter-node.js/util");
const datatype_1 = require("@project-chip/matter.js/datatype");
// @ts-ignore
const pick_port_1 = __importDefault(require("pick-port"));
var DeviceType;
(function (DeviceType) {
    DeviceType["OnOffPluginUnitDevice"] = "OnOffPluginUnitDevice";
    DeviceType["OnOffLightDevice"] = "OnOffLightDevice";
})(DeviceType || (exports.DeviceType = DeviceType = {}));
class MatterOnOffDevice {
    commissioningServer;
    uniqueId;
    device;
    port;
    deviceType;
    deviceName = 'Matter test device';
    vendorName = 'Node RED Matter';
    passcode = 20202021;
    discriminator;
    // product name / id and vendor id should match what is in the device certificate
    vendorId = 0xfff1;
    productName;
    productId;
    constructor(deviceType, port, uniqueId, discriminator, productId) {
        this.port = Number(port);
        this.deviceType = deviceType;
        this.uniqueId = uniqueId;
        this.discriminator = discriminator;
        this.productId = productId;
        this.productName = this.deviceType.substring(0, 32);
    }
    async start({ aggregated, onStatusChange, }) {
        const port = this.port === 0
            ? await (0, pick_port_1.default)({ type: 'udp', minPort: 5400, maxPort: 5540 })
            : this.port;
        /**
         * Create Device instance and add needed Listener
         *
         * Create an instance of the matter device class you want to use.
         * This example uses the OnOffLightDevice or OnOffPluginUnitDevice depending on the value of the type  parameter.
         * To execute the on/off scripts defined as parameters a listener for the onOff attribute is registered via the
         * device specific API.
         *
         * The below logic also adds command handlers for commands of clusters that normally are handled device internally
         * like identify that can be implemented with the logic when these commands are called.
         */
        switch (this.deviceType) {
            case DeviceType.OnOffPluginUnitDevice:
                this.device = new device_1.OnOffPluginUnitDevice();
                break;
            case DeviceType.OnOffLightDevice:
                this.device = new device_1.OnOffLightDevice();
                break;
            default:
                throw new Error('Unknown device type');
        }
        this.device.addOnOffListener((on) => {
            (0, util_1.commandExecutor)(on ? 'on' : 'off')?.();
            onStatusChange(on);
        });
        this.device.isOn().then((on) => {
            onStatusChange(on);
        });
        if (aggregated)
            return;
        const commissioningServer = new matter_node_js_1.CommissioningServer({
            port,
            deviceName: this.deviceName,
            deviceType: (0, datatype_1.DeviceTypeId)(this.device.deviceType),
            passcode: this.passcode,
            discriminator: this.discriminator,
            basicInformation: {
                vendorName: this.vendorName,
                vendorId: (0, datatype_1.VendorId)(this.vendorId),
                nodeLabel: this.productName,
                productName: this.productName,
                productLabel: this.productName,
                productId: this.productId,
                serialNumber: `node-red-matter-${this.uniqueId}`,
            },
            delayedAnnouncement: false,
        });
        commissioningServer.addDevice(this.device);
        this.commissioningServer = commissioningServer;
        (0, util_1.logEndpoint)(commissioningServer.getRootEndpoint());
        return commissioningServer;
    }
    async getPairingData() {
        if (this.commissioningServer == null) {
            throw new Error('Commissioning server not initialized');
        }
        /**
         * Print Pairing Information
         *
         * If the device is not already commissioned (this info is stored in the storage system) then get and print the
         * pairing details. This includes the QR code that can be scanned by the Matter app to pair the device.
         */
        const commissioned = this.commissioningServer.isCommissioned();
        const pairingData = this.commissioningServer.getPairingCode({
            ble: false,
            softAccessPoint: false,
            onIpNetwork: false,
        });
        const { qrCode, qrPairingCode, manualPairingCode } = pairingData;
        return {
            qrCode,
            qrPairingCode,
            manualPairingCode,
            qrCodeUrl: `https://project-chip.github.io/connectedhomeip/qrcode.html?data=${qrPairingCode}`,
            commissioned,
        };
    }
}
exports.MatterOnOffDevice = MatterOnOffDevice;
