"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;
    };
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Adapter = void 0;
const node_events_1 = __importDefault(require("node:events"));
const Zcl = __importStar(require("../zspec/zcl"));
const adapterDiscovery_1 = require("./adapterDiscovery");
class Adapter extends node_events_1.default.EventEmitter {
    hasZdoMessageOverhead;
    manufacturerID;
    networkOptions;
    adapterOptions;
    serialPortOptions;
    backupPath;
    constructor(networkOptions, serialPortOptions, backupPath, adapterOptions) {
        super();
        this.hasZdoMessageOverhead = true;
        this.manufacturerID = Zcl.ManufacturerCode.RESERVED_10;
        this.networkOptions = networkOptions;
        this.adapterOptions = adapterOptions;
        this.serialPortOptions = serialPortOptions;
        this.backupPath = backupPath;
    }
    /**
     * Utility
     */
    static async create(networkOptions, serialPortOptions, backupPath, adapterOptions) {
        const discovered = await (0, adapterDiscovery_1.discoverAdapter)(serialPortOptions.adapter, serialPortOptions.path);
        serialPortOptions.adapter = discovered.adapter;
        serialPortOptions.path = discovered.path;
        if (serialPortOptions.baudRate === undefined && discovered.baudRate !== undefined) {
            serialPortOptions.baudRate = discovered.baudRate;
        }
        if (serialPortOptions.rtscts === undefined && discovered.rtscts !== undefined) {
            serialPortOptions.rtscts = discovered.rtscts;
        }
        switch (discovered.adapter) {
            case "zstack": {
                const { ZStackAdapter } = await import("./z-stack/adapter/zStackAdapter.js");
                return new ZStackAdapter(networkOptions, serialPortOptions, backupPath, adapterOptions);
            }
            case "ember": {
                const { EmberAdapter } = await import("./ember/adapter/emberAdapter.js");
                return new EmberAdapter(networkOptions, serialPortOptions, backupPath, adapterOptions);
            }
            case "deconz": {
                const { DeconzAdapter } = await import("./deconz/adapter/deconzAdapter.js");
                return new DeconzAdapter(networkOptions, serialPortOptions, backupPath, adapterOptions);
            }
            case "zigate": {
                const { ZiGateAdapter } = await import("./zigate/adapter/zigateAdapter.js");
                return new ZiGateAdapter(networkOptions, serialPortOptions, backupPath, adapterOptions);
            }
            case "zboss": {
                const { ZBOSSAdapter } = await import("./zboss/adapter/zbossAdapter.js");
                return new ZBOSSAdapter(networkOptions, serialPortOptions, backupPath, adapterOptions);
            }
            case "zoh": {
                const { ZoHAdapter } = await import("./zoh/adapter/zohAdapter.js");
                return new ZoHAdapter(networkOptions, serialPortOptions, backupPath, adapterOptions);
            }
            // @deprecated
            case "ezsp": {
                const { EZSPAdapter } = await import("./ezsp/adapter/ezspAdapter.js");
                return new EZSPAdapter(networkOptions, serialPortOptions, backupPath, adapterOptions);
            }
            default: {
                throw new Error(`Adapter '${discovered.adapter}' does not exists, possible options: zstack, ember, deconz, zigate, zboss, zoh, ezsp`);
            }
        }
    }
    static clusterWaitressTimeoutFormatter(matcher, timeout) {
        return `Timeout after ${timeout}ms [address=${matcher.address} endpoint=${matcher.endpoint} clusterId=${matcher.clusterId} cmdId=${matcher.commandId} tsn=${matcher.transactionSequenceNumber}]`;
    }
    static zclWaitressValidator(payload, matcher) {
        const { header, address, clusterID, endpoint } = payload;
        return (
        // no sender in Touchlink
        (matcher.address === undefined || address === matcher.address) &&
            clusterID === matcher.clusterId &&
            endpoint === matcher.endpoint &&
            (matcher.transactionSequenceNumber === undefined || header.transactionSequenceNumber === matcher.transactionSequenceNumber) &&
            (header.commandIdentifier === matcher.commandId ||
                // defaultRsp
                (header.frameControl.frameType === Zcl.FrameType.GLOBAL &&
                    header.commandIdentifier === 0x0b &&
                    (matcher.defaultRspCommandId === undefined || payload.data[payload.data.byteLength - 2] === matcher.defaultRspCommandId))));
    }
}
exports.Adapter = Adapter;
exports.default = Adapter;
//# sourceMappingURL=adapter.js.map