import { __esDecorate, __runInitializers } from "tslib";
import * as __validateArgs from "./ThermostatOperatingStateCC._validateArgs.js";
const { validateArgs_ThermostatOperatingStateCCAPI_getLogging } = __validateArgs;
import { CommandClasses, MessagePriority, encodeBitMask, parseBitMask, validatePayload, } from "@zwave-js/core";
import { Bytes, getEnumMemberName } from "@zwave-js/shared";
import { CCAPI, POLL_VALUE, PhysicalCCAPI, throwUnsupportedProperty, } from "../lib/API.js";
import { CommandClass, } from "../lib/CommandClass.js";
import { API, CCCommand, ccValueProperty, ccValues, commandClass, expectedCCResponse, implementedVersion, } from "../lib/CommandClassDecorators.js";
import { ThermostatOperatingState, ThermostatOperatingStateCommand, } from "../lib/_Types.js";
import { ThermostatOperatingStateCCValues } from "./_CCValues.generated.js";
export { ThermostatOperatingStateCCValues };
// @noSetValueAPI This CC is read-only
let ThermostatOperatingStateCCAPI = (() => {
    let _classDecorators = [API(CommandClasses["Thermostat Operating State"])];
    let _classDescriptor;
    let _classExtraInitializers = [];
    let _classThis;
    let _classSuper = PhysicalCCAPI;
    let _instanceExtraInitializers = [];
    let _getLogging_decorators;
    var ThermostatOperatingStateCCAPI = class extends _classSuper {
        static { _classThis = this; }
        static {
            const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
            _getLogging_decorators = [validateArgs_ThermostatOperatingStateCCAPI_getLogging()];
            __esDecorate(this, null, _getLogging_decorators, { kind: "method", name: "getLogging", static: false, private: false, access: { has: obj => "getLogging" in obj, get: obj => obj.getLogging }, metadata: _metadata }, null, _instanceExtraInitializers);
            __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
            ThermostatOperatingStateCCAPI = _classThis = _classDescriptor.value;
            if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
            __runInitializers(_classThis, _classExtraInitializers);
        }
        supportsCommand(cmd) {
            switch (cmd) {
                case ThermostatOperatingStateCommand.Get:
                    return true; // This is mandatory
                case ThermostatOperatingStateCommand.LoggingSupportedGet:
                case ThermostatOperatingStateCommand.LoggingGet:
                    return this.version >= 2;
            }
            return super.supportsCommand(cmd);
        }
        get [POLL_VALUE]() {
            return async function ({ property }) {
                switch (property) {
                    case "state":
                        return this.get();
                    default:
                        throwUnsupportedProperty(this.ccId, property);
                }
            };
        }
        async get() {
            this.assertSupportsCommand(ThermostatOperatingStateCommand, ThermostatOperatingStateCommand.Get);
            const cc = new ThermostatOperatingStateCCGet({
                nodeId: this.endpoint.nodeId,
                endpointIndex: this.endpoint.index,
            });
            const response = await this.host.sendCommand(cc, this.commandOptions);
            return response?.state;
        }
        async getSupportedLoggingTypes() {
            this.assertSupportsCommand(ThermostatOperatingStateCommand, ThermostatOperatingStateCommand.LoggingSupportedGet);
            const cc = new ThermostatOperatingStateCCLoggingSupportedGet({
                nodeId: this.endpoint.nodeId,
                endpointIndex: this.endpoint.index,
            });
            const response = await this.host.sendCommand(cc, this.commandOptions);
            return response?.supportedLoggingTypes;
        }
        async getLogging(states) {
            this.assertSupportsCommand(ThermostatOperatingStateCommand, ThermostatOperatingStateCommand.LoggingGet);
            const cc = new ThermostatOperatingStateCCLoggingGet({
                nodeId: this.endpoint.nodeId,
                endpointIndex: this.endpoint.index,
                requestedStates: states,
            });
            const response = await this.host.sendCommand(cc, this.commandOptions);
            return response?.loggingData;
        }
        constructor() {
            super(...arguments);
            __runInitializers(this, _instanceExtraInitializers);
        }
    };
    return ThermostatOperatingStateCCAPI = _classThis;
})();
export { ThermostatOperatingStateCCAPI };
let ThermostatOperatingStateCC = (() => {
    let _classDecorators = [commandClass(CommandClasses["Thermostat Operating State"]), implementedVersion(2), ccValues(ThermostatOperatingStateCCValues)];
    let _classDescriptor;
    let _classExtraInitializers = [];
    let _classThis;
    let _classSuper = CommandClass;
    var ThermostatOperatingStateCC = 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);
            ThermostatOperatingStateCC = _classThis = _classDescriptor.value;
            if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
            __runInitializers(_classThis, _classExtraInitializers);
        }
        async interview(ctx) {
            const node = this.getNode(ctx);
            ctx.logNode(node.id, {
                endpoint: this.endpointIndex,
                message: `Interviewing ${this.ccName}...`,
                direction: "none",
            });
            await this.refreshValues(ctx);
            this.setInterviewComplete(ctx, true);
        }
        async refreshValues(ctx, options) {
            const node = this.getNode(ctx);
            const endpoint = this.getEndpoint(ctx);
            const api = CCAPI.create(CommandClasses["Thermostat Operating State"], ctx, endpoint).withOptions({
                priority: options?.priority ?? MessagePriority.NodeQuery,
            });
            ctx.logNode(node.id, {
                endpoint: this.endpointIndex,
                message: "querying thermostat operating state...",
                direction: "outbound",
            });
            const state = await api.get();
            if (state != undefined) {
                ctx.logNode(node.id, {
                    endpoint: this.endpointIndex,
                    message: `received current thermostat operating state: ${getEnumMemberName(ThermostatOperatingState, state)}`,
                    direction: "inbound",
                });
            }
        }
    };
    return ThermostatOperatingStateCC = _classThis;
})();
export { ThermostatOperatingStateCC };
let ThermostatOperatingStateCCReport = (() => {
    let _classDecorators = [CCCommand(ThermostatOperatingStateCommand.Report), ccValueProperty("state", ThermostatOperatingStateCCValues.operatingState)];
    let _classDescriptor;
    let _classExtraInitializers = [];
    let _classThis;
    let _classSuper = ThermostatOperatingStateCC;
    var ThermostatOperatingStateCCReport = 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);
            ThermostatOperatingStateCCReport = _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.state = options.state;
        }
        static from(raw, ctx) {
            validatePayload(raw.payload.length >= 1);
            const state = raw.payload[0];
            validatePayload(state <= ThermostatOperatingState["3rd Stage Aux Heat"]);
            return new this({
                nodeId: ctx.sourceNodeId,
                state,
            });
        }
        state;
        serialize(ctx) {
            this.payload = Bytes.from([this.state]);
            return super.serialize(ctx);
        }
        toLogEntry(ctx) {
            return {
                ...super.toLogEntry(ctx),
                message: {
                    state: getEnumMemberName(ThermostatOperatingState, this.state),
                },
            };
        }
    };
    return ThermostatOperatingStateCCReport = _classThis;
})();
export { ThermostatOperatingStateCCReport };
let ThermostatOperatingStateCCGet = (() => {
    let _classDecorators = [CCCommand(ThermostatOperatingStateCommand.Get), expectedCCResponse(ThermostatOperatingStateCCReport)];
    let _classDescriptor;
    let _classExtraInitializers = [];
    let _classThis;
    let _classSuper = ThermostatOperatingStateCC;
    var ThermostatOperatingStateCCGet = 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);
            ThermostatOperatingStateCCGet = _classThis = _classDescriptor.value;
            if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
            __runInitializers(_classThis, _classExtraInitializers);
        }
    };
    return ThermostatOperatingStateCCGet = _classThis;
})();
export { ThermostatOperatingStateCCGet };
let ThermostatOperatingStateCCLoggingSupportedReport = (() => {
    let _classDecorators = [CCCommand(ThermostatOperatingStateCommand.LoggingSupportedReport)];
    let _classDescriptor;
    let _classExtraInitializers = [];
    let _classThis;
    let _classSuper = ThermostatOperatingStateCC;
    var ThermostatOperatingStateCCLoggingSupportedReport = 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);
            ThermostatOperatingStateCCLoggingSupportedReport = _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.supportedLoggingTypes = options.supportedLoggingTypes;
        }
        static from(raw, ctx) {
            // Bit 0 is not allocated, bit 1 = Operating State 1, etc.
            const supportedLoggingTypes = parseBitMask(raw.payload, ThermostatOperatingState["Idle"])
                // Bit 0 MUST be set to zero, so we ignore it when set
                .filter((state) => state !== ThermostatOperatingState.Idle);
            return new this({
                nodeId: ctx.sourceNodeId,
                supportedLoggingTypes,
            });
        }
        supportedLoggingTypes;
        serialize(ctx) {
            const supportedLoggingTypes = this.supportedLoggingTypes
                // Bit 0 MUST be set to zero, so we filter it out
                .filter((t) => t !== ThermostatOperatingState.Idle);
            this.payload = encodeBitMask(supportedLoggingTypes, undefined, ThermostatOperatingState["Idle"]);
            return super.serialize(ctx);
        }
        toLogEntry(ctx) {
            return {
                ...super.toLogEntry(ctx),
                message: {
                    "supported logging types": this.supportedLoggingTypes
                        .map((t) => `\n· ${getEnumMemberName(ThermostatOperatingState, t)}`)
                        .join(""),
                },
            };
        }
    };
    return ThermostatOperatingStateCCLoggingSupportedReport = _classThis;
})();
export { ThermostatOperatingStateCCLoggingSupportedReport };
let ThermostatOperatingStateCCLoggingSupportedGet = (() => {
    let _classDecorators = [CCCommand(ThermostatOperatingStateCommand.LoggingSupportedGet), expectedCCResponse(ThermostatOperatingStateCCLoggingSupportedReport)];
    let _classDescriptor;
    let _classExtraInitializers = [];
    let _classThis;
    let _classSuper = ThermostatOperatingStateCC;
    var ThermostatOperatingStateCCLoggingSupportedGet = 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);
            ThermostatOperatingStateCCLoggingSupportedGet = _classThis = _classDescriptor.value;
            if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
            __runInitializers(_classThis, _classExtraInitializers);
        }
    };
    return ThermostatOperatingStateCCLoggingSupportedGet = _classThis;
})();
export { ThermostatOperatingStateCCLoggingSupportedGet };
let ThermostatOperatingStateCCLoggingReport = (() => {
    let _classDecorators = [CCCommand(ThermostatOperatingStateCommand.LoggingReport)];
    let _classDescriptor;
    let _classExtraInitializers = [];
    let _classThis;
    let _classSuper = ThermostatOperatingStateCC;
    var ThermostatOperatingStateCCLoggingReport = 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);
            ThermostatOperatingStateCCLoggingReport = _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.reportsToFollow = options.reportsToFollow;
            this.loggingData = options.loggingData;
        }
        static from(raw, ctx) {
            validatePayload(raw.payload.length >= 1);
            const reportsToFollow = raw.payload[0];
            // Each log entry is 5 bytes:
            // Reserved[7:4]+StateType[3:0], TodayH, TodayM, YesterdayH, YesterdayM
            const loggingData = new Map();
            let offset = 1;
            while (offset + 5 <= raw.payload.length) {
                const state = raw.payload[offset++]
                    & 0b1111;
                loggingData.set(state, {
                    usageTodayHours: raw.payload[offset++],
                    usageTodayMinutes: raw.payload[offset++],
                    usageYesterdayHours: raw.payload[offset++],
                    usageYesterdayMinutes: raw.payload[offset++],
                });
            }
            return new this({
                nodeId: ctx.sourceNodeId,
                reportsToFollow,
                loggingData,
            });
        }
        reportsToFollow;
        loggingData;
        getPartialCCSessionId() {
            return {};
        }
        expectMoreMessages() {
            return this.reportsToFollow > 0;
        }
        mergePartialCCs(partials, _ctx) {
            // Merge all logging data maps from partial reports
            const merged = new Map();
            for (const partial of partials) {
                for (const [state, data] of partial.loggingData) {
                    merged.set(state, data);
                }
            }
            for (const [state, data] of this.loggingData) {
                merged.set(state, data);
            }
            this.loggingData = merged;
            return Promise.resolve();
        }
        serialize(ctx) {
            this.payload = new Bytes(1 + this.loggingData.size * 5);
            this.payload[0] = this.reportsToFollow;
            let offset = 1;
            for (const [state, entry] of this.loggingData) {
                this.payload[offset++] = state & 0b1111;
                this.payload[offset++] = entry.usageTodayHours;
                this.payload[offset++] = entry.usageTodayMinutes;
                this.payload[offset++] = entry.usageYesterdayHours;
                this.payload[offset++] = entry.usageYesterdayMinutes;
            }
            return super.serialize(ctx);
        }
        toLogEntry(ctx) {
            const message = {
                "reports to follow": this.reportsToFollow,
            };
            for (const [state, entry] of this.loggingData) {
                const stateName = getEnumMemberName(ThermostatOperatingState, state);
                message[`${stateName} today`] =
                    `${entry.usageTodayHours}h ${entry.usageTodayMinutes}m`;
                message[`${stateName} yesterday`] =
                    `${entry.usageYesterdayHours}h ${entry.usageYesterdayMinutes}m`;
            }
            return {
                ...super.toLogEntry(ctx),
                message,
            };
        }
    };
    return ThermostatOperatingStateCCLoggingReport = _classThis;
})();
export { ThermostatOperatingStateCCLoggingReport };
let ThermostatOperatingStateCCLoggingGet = (() => {
    let _classDecorators = [CCCommand(ThermostatOperatingStateCommand.LoggingGet), expectedCCResponse(ThermostatOperatingStateCCLoggingReport)];
    let _classDescriptor;
    let _classExtraInitializers = [];
    let _classThis;
    let _classSuper = ThermostatOperatingStateCC;
    var ThermostatOperatingStateCCLoggingGet = 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);
            ThermostatOperatingStateCCLoggingGet = _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.requestedStates = options.requestedStates;
        }
        static from(raw, ctx) {
            const requestedStates = parseBitMask(raw.payload, ThermostatOperatingState["Idle"]);
            return new this({
                nodeId: ctx.sourceNodeId,
                requestedStates,
            });
        }
        requestedStates;
        serialize(ctx) {
            this.payload = encodeBitMask(this.requestedStates, undefined, ThermostatOperatingState["Idle"]);
            return super.serialize(ctx);
        }
        toLogEntry(ctx) {
            return {
                ...super.toLogEntry(ctx),
                message: {
                    "requested states": this.requestedStates
                        .map((t) => getEnumMemberName(ThermostatOperatingState, t))
                        .join(", "),
                },
            };
        }
    };
    return ThermostatOperatingStateCCLoggingGet = _classThis;
})();
export { ThermostatOperatingStateCCLoggingGet };
//# sourceMappingURL=ThermostatOperatingStateCC.js.map