import { __esDecorate, __runInitializers } from "tslib";
import { BasicDeviceClass, encodeNodeUpdatePayload, getCCName, parseCCList, parseNodeID, parseNodeUpdatePayload, } from "@zwave-js/core";
import { createSimpleReflectionDecorator } from "@zwave-js/core/reflection";
import { FunctionType, Message, MessageType, messageTypes, } from "@zwave-js/serial";
import { Bytes, buffer2hex, getEnumMemberName, } from "@zwave-js/shared";
export var ApplicationUpdateTypes;
(function (ApplicationUpdateTypes) {
    ApplicationUpdateTypes[ApplicationUpdateTypes["SmartStart_NodeInfo_Received"] = 134] = "SmartStart_NodeInfo_Received";
    ApplicationUpdateTypes[ApplicationUpdateTypes["SmartStart_HomeId_Received"] = 133] = "SmartStart_HomeId_Received";
    ApplicationUpdateTypes[ApplicationUpdateTypes["SmartStart_LongRange_HomeId_Received"] = 135] = "SmartStart_LongRange_HomeId_Received";
    ApplicationUpdateTypes[ApplicationUpdateTypes["NodeInfo_Received"] = 132] = "NodeInfo_Received";
    ApplicationUpdateTypes[ApplicationUpdateTypes["NodeInfo_RequestDone"] = 130] = "NodeInfo_RequestDone";
    ApplicationUpdateTypes[ApplicationUpdateTypes["NodeInfo_RequestFailed"] = 129] = "NodeInfo_RequestFailed";
    ApplicationUpdateTypes[ApplicationUpdateTypes["RoutingPending"] = 128] = "RoutingPending";
    ApplicationUpdateTypes[ApplicationUpdateTypes["Node_Added"] = 64] = "Node_Added";
    ApplicationUpdateTypes[ApplicationUpdateTypes["Node_Removed"] = 32] = "Node_Removed";
    ApplicationUpdateTypes[ApplicationUpdateTypes["SUC_IdChanged"] = 16] = "SUC_IdChanged";
})(ApplicationUpdateTypes || (ApplicationUpdateTypes = {}));
const { decorator: applicationUpdateType, lookupConstructor: getApplicationUpdateRequestConstructor, lookupValue: getApplicationUpdateType, } = createSimpleReflectionDecorator({
    name: "applicationUpdateType",
});
let ApplicationUpdateRequest = (() => {
    let _classDecorators = [messageTypes(MessageType.Request, FunctionType.ApplicationUpdateRequest)];
    let _classDescriptor;
    let _classExtraInitializers = [];
    let _classThis;
    let _classSuper = Message;
    var ApplicationUpdateRequest = class extends _classSuper {
        static { _classThis = this; }
        static {
            const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
            __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
            ApplicationUpdateRequest = _classThis = _classDescriptor.value;
            if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
            __runInitializers(_classThis, _classExtraInitializers);
        }
        constructor(options = {}) {
            super(options);
            this.updateType = options.updateType ?? getApplicationUpdateType(this);
        }
        static from(raw, ctx) {
            const updateType = raw.payload[0];
            const payload = raw.payload.subarray(1);
            const CommandConstructor = getApplicationUpdateRequestConstructor(updateType);
            if (CommandConstructor) {
                return CommandConstructor.from(raw.withPayload(payload), ctx);
            }
            const ret = new ApplicationUpdateRequest({
                updateType,
            });
            ret.payload = payload;
            return ret;
        }
        updateType;
        serialize(ctx) {
            this.payload = Bytes.concat([
                [this.updateType],
                this.payload,
            ]);
            return super.serialize(ctx);
        }
    };
    return ApplicationUpdateRequest = _classThis;
})();
export { ApplicationUpdateRequest };
export class ApplicationUpdateRequestWithNodeInfo extends ApplicationUpdateRequest {
    constructor(options) {
        super(options);
        this.nodeId = options.nodeInformation.nodeId;
        this.nodeInformation = options.nodeInformation;
    }
    static from(raw, ctx) {
        const nodeInformation = parseNodeUpdatePayload(raw.payload, ctx.nodeIdType);
        return new this({
            nodeInformation,
        });
    }
    nodeId;
    nodeInformation;
    serialize(ctx) {
        this.payload = encodeNodeUpdatePayload(this.nodeInformation, ctx.nodeIdType);
        return super.serialize(ctx);
    }
}
let ApplicationUpdateRequestNodeInfoReceived = (() => {
    let _classDecorators = [applicationUpdateType(ApplicationUpdateTypes.NodeInfo_Received)];
    let _classDescriptor;
    let _classExtraInitializers = [];
    let _classThis;
    let _classSuper = ApplicationUpdateRequestWithNodeInfo;
    var ApplicationUpdateRequestNodeInfoReceived = class extends _classSuper {
        static { _classThis = this; }
        static {
            const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
            __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
            ApplicationUpdateRequestNodeInfoReceived = _classThis = _classDescriptor.value;
            if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
            __runInitializers(_classThis, _classExtraInitializers);
        }
    };
    return ApplicationUpdateRequestNodeInfoReceived = _classThis;
})();
export { ApplicationUpdateRequestNodeInfoReceived };
let ApplicationUpdateRequestNodeInfoRequestFailed = (() => {
    let _classDecorators = [applicationUpdateType(ApplicationUpdateTypes.NodeInfo_RequestFailed)];
    let _classDescriptor;
    let _classExtraInitializers = [];
    let _classThis;
    let _classSuper = ApplicationUpdateRequest;
    var ApplicationUpdateRequestNodeInfoRequestFailed = class extends _classSuper {
        static { _classThis = this; }
        static {
            const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
            __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
            ApplicationUpdateRequestNodeInfoRequestFailed = _classThis = _classDescriptor.value;
            if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
            __runInitializers(_classThis, _classExtraInitializers);
        }
        isOK() {
            return false;
        }
    };
    return ApplicationUpdateRequestNodeInfoRequestFailed = _classThis;
})();
export { ApplicationUpdateRequestNodeInfoRequestFailed };
let ApplicationUpdateRequestNodeAdded = (() => {
    let _classDecorators = [applicationUpdateType(ApplicationUpdateTypes.Node_Added)];
    let _classDescriptor;
    let _classExtraInitializers = [];
    let _classThis;
    let _classSuper = ApplicationUpdateRequestWithNodeInfo;
    var ApplicationUpdateRequestNodeAdded = class extends _classSuper {
        static { _classThis = this; }
        static {
            const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
            __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
            ApplicationUpdateRequestNodeAdded = _classThis = _classDescriptor.value;
            if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
            __runInitializers(_classThis, _classExtraInitializers);
        }
    };
    return ApplicationUpdateRequestNodeAdded = _classThis;
})();
export { ApplicationUpdateRequestNodeAdded };
let ApplicationUpdateRequestNodeRemoved = (() => {
    let _classDecorators = [applicationUpdateType(ApplicationUpdateTypes.Node_Removed)];
    let _classDescriptor;
    let _classExtraInitializers = [];
    let _classThis;
    let _classSuper = ApplicationUpdateRequest;
    var ApplicationUpdateRequestNodeRemoved = class extends _classSuper {
        static { _classThis = this; }
        static {
            const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
            __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
            ApplicationUpdateRequestNodeRemoved = _classThis = _classDescriptor.value;
            if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
            __runInitializers(_classThis, _classExtraInitializers);
        }
        constructor(options) {
            super(options);
            this.nodeId = options.nodeId;
        }
        static from(raw, ctx) {
            const { nodeId } = parseNodeID(raw.payload, ctx.nodeIdType, 0);
            // byte 1/2 is 0, meaning unknown
            return new this({
                nodeId,
            });
        }
        nodeId;
    };
    return ApplicationUpdateRequestNodeRemoved = _classThis;
})();
export { ApplicationUpdateRequestNodeRemoved };
class ApplicationUpdateRequestSmartStartHomeIDReceivedBase extends ApplicationUpdateRequest {
    constructor(options) {
        super(options);
        // TODO: Check implementation:
        this.remoteNodeId = options.remoteNodeId;
        this.nwiHomeId = options.nwiHomeId;
        this.basicDeviceClass = options.basicDeviceClass;
        this.genericDeviceClass = options.genericDeviceClass;
        this.specificDeviceClass = options.specificDeviceClass;
        this.supportedCCs = options.supportedCCs;
    }
    static from(raw, ctx) {
        let offset = 0;
        const { nodeId: remoteNodeId, bytesRead: nodeIdBytes } = parseNodeID(raw.payload, ctx.nodeIdType, offset);
        offset += nodeIdBytes;
        // next byte is rxStatus
        offset++;
        const nwiHomeId = raw.payload.subarray(offset, offset + 4);
        offset += 4;
        const ccLength = raw.payload[offset++];
        const basicDeviceClass = raw.payload[offset++];
        const genericDeviceClass = raw.payload[offset++];
        const specificDeviceClass = raw.payload[offset++];
        const supportedCCs = parseCCList(raw.payload.subarray(offset, offset + ccLength)).supportedCCs;
        return new this({
            remoteNodeId,
            nwiHomeId,
            basicDeviceClass,
            genericDeviceClass,
            specificDeviceClass,
            supportedCCs,
        });
    }
    remoteNodeId;
    nwiHomeId;
    basicDeviceClass;
    genericDeviceClass;
    specificDeviceClass;
    supportedCCs;
    toLogEntry() {
        const message = {
            type: getEnumMemberName(ApplicationUpdateTypes, this.updateType),
            "remote node ID": this.remoteNodeId,
            "NWI home ID": buffer2hex(this.nwiHomeId),
            "basic device class": getEnumMemberName(BasicDeviceClass, this.basicDeviceClass),
            "generic device class": this.genericDeviceClass,
            "specific device class": this.specificDeviceClass,
            "supported CCs": this.supportedCCs
                .map((cc) => `\n· ${getCCName(cc)}`)
                .join(""),
        };
        return {
            ...super.toLogEntry(),
            message,
        };
    }
}
let ApplicationUpdateRequestSmartStartHomeIDReceived = (() => {
    let _classDecorators = [applicationUpdateType(ApplicationUpdateTypes.SmartStart_HomeId_Received)];
    let _classDescriptor;
    let _classExtraInitializers = [];
    let _classThis;
    let _classSuper = ApplicationUpdateRequestSmartStartHomeIDReceivedBase;
    var ApplicationUpdateRequestSmartStartHomeIDReceived = class extends _classSuper {
        static { _classThis = this; }
        static {
            const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
            __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
            ApplicationUpdateRequestSmartStartHomeIDReceived = _classThis = _classDescriptor.value;
            if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
            __runInitializers(_classThis, _classExtraInitializers);
        }
    };
    return ApplicationUpdateRequestSmartStartHomeIDReceived = _classThis;
})();
export { ApplicationUpdateRequestSmartStartHomeIDReceived };
let ApplicationUpdateRequestSmartStartLongRangeHomeIDReceived = (() => {
    let _classDecorators = [applicationUpdateType(ApplicationUpdateTypes.SmartStart_LongRange_HomeId_Received)];
    let _classDescriptor;
    let _classExtraInitializers = [];
    let _classThis;
    let _classSuper = ApplicationUpdateRequestSmartStartHomeIDReceivedBase;
    var ApplicationUpdateRequestSmartStartLongRangeHomeIDReceived = class extends _classSuper {
        static { _classThis = this; }
        static {
            const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
            __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
            ApplicationUpdateRequestSmartStartLongRangeHomeIDReceived = _classThis = _classDescriptor.value;
            if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
            __runInitializers(_classThis, _classExtraInitializers);
        }
    };
    return ApplicationUpdateRequestSmartStartLongRangeHomeIDReceived = _classThis;
})();
export { ApplicationUpdateRequestSmartStartLongRangeHomeIDReceived };
let ApplicationUpdateRequestSUCIdChanged = (() => {
    let _classDecorators = [applicationUpdateType(ApplicationUpdateTypes.SUC_IdChanged)];
    let _classDescriptor;
    let _classExtraInitializers = [];
    let _classThis;
    let _classSuper = ApplicationUpdateRequest;
    var ApplicationUpdateRequestSUCIdChanged = class extends _classSuper {
        static { _classThis = this; }
        static {
            const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
            __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
            ApplicationUpdateRequestSUCIdChanged = _classThis = _classDescriptor.value;
            if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
            __runInitializers(_classThis, _classExtraInitializers);
        }
        constructor(options) {
            super(options);
            this.sucNodeID = options.sucNodeID;
        }
        static from(raw, ctx) {
            const { nodeId: sucNodeID } = parseNodeID(raw.payload, ctx.nodeIdType, 0);
            // byte 1/2 is 0, meaning unknown
            return new this({
                sucNodeID,
            });
        }
        sucNodeID;
        toLogEntry() {
            const message = {
                type: getEnumMemberName(ApplicationUpdateTypes, this.updateType),
                "SUC node ID": this.sucNodeID,
            };
            return {
                ...super.toLogEntry(),
                message,
            };
        }
    };
    return ApplicationUpdateRequestSUCIdChanged = _classThis;
})();
export { ApplicationUpdateRequestSUCIdChanged };
//# sourceMappingURL=ApplicationUpdateRequest.js.map