import { InterviewStage } from "@zwave-js/core";
import { cacheKeys } from "../../driver/NetworkCache.js";
import { createNodeReadyMachine, } from "../NodeReadyMachine.js";
import { createNodeStatusMachine, nodeStatusMachineStateToNodeStatus, } from "../NodeStatusMachine.js";
import { NodeStatus } from "../_Types.js";
import { NodeEventsMixin } from "./10_Events.js";
export class NodeStatusMixin extends NodeEventsMixin {
    constructor(nodeId, driver, index, deviceClass, supportedCCs) {
        super(nodeId, driver, index, deviceClass, supportedCCs);
        // Create the state machines
        this.statusMachine = createNodeStatusMachine(this);
        this.readyMachine = createNodeReadyMachine();
    }
    statusMachine;
    _status = NodeStatus.Unknown;
    /**
     * Which status the node is believed to be in
     */
    get status() {
        return this._status;
    }
    restartStatusMachine() {
        this.statusMachine.restart();
        this.onStatusChange(NodeStatus.Unknown);
    }
    updateStatusMachine(input) {
        const newState = this.statusMachine.next(input)?.newState;
        if (newState) {
            this.statusMachine.transition(newState);
            this.onStatusChange(nodeStatusMachineStateToNodeStatus(newState.value));
        }
    }
    onStatusChange(newStatus) {
        // Ignore duplicate events
        if (newStatus === this._status)
            return;
        const oldStatus = this._status;
        this._status = newStatus;
        if (this._status === NodeStatus.Asleep) {
            this._emit("sleep", this, oldStatus);
        }
        else if (this._status === NodeStatus.Awake) {
            this._emit("wake up", this, oldStatus);
        }
        else if (this._status === NodeStatus.Dead) {
            this._emit("dead", this, oldStatus);
        }
        else if (this._status === NodeStatus.Alive) {
            this._emit("alive", this, oldStatus);
        }
        // To be marked ready, a node must be known to be not dead.
        // This means that listening nodes must have communicated with us and
        // sleeping nodes are assumed to be ready
        this.updateReadyMachine({
            value: this._status !== NodeStatus.Unknown
                && this._status !== NodeStatus.Dead
                ? "NOT_DEAD"
                : "MAYBE_DEAD",
        });
    }
    /**
     * @internal
     * Marks this node as dead (if applicable)
     */
    markAsDead() {
        this.updateStatusMachine({ value: "DEAD" });
    }
    /**
     * @internal
     * Marks this node as alive (if applicable)
     */
    markAsAlive() {
        this.updateStatusMachine({ value: "ALIVE" });
    }
    /**
     * @internal
     * Marks this node as asleep (if applicable)
     */
    markAsAsleep() {
        this.updateStatusMachine({ value: "ASLEEP" });
    }
    /**
     * @internal
     * Marks this node as awake (if applicable)
     */
    markAsAwake() {
        this.updateStatusMachine({ value: "AWAKE" });
    }
    // The node is only ready when the interview has been completed
    // to a certain degree
    readyMachine;
    _ready = false;
    restartReadyMachine() {
        this.readyMachine.restart();
        this.onReadyChange(false);
    }
    updateReadyMachine(input) {
        const newState = this.readyMachine.next(input)?.newState;
        if (newState) {
            this.readyMachine.transition(newState);
            this.onReadyChange(newState.value === "ready");
        }
    }
    onReadyChange(ready) {
        // Ignore duplicate events
        if (ready === this._ready)
            return;
        this._ready = ready;
        if (ready)
            this._emit("ready", this);
    }
    /**
     * Whether the node is ready to be used
     */
    get ready() {
        return this._ready;
    }
    set ready(ready) {
        this._ready = ready;
    }
    get interviewStage() {
        return (this.driver.cacheGet(cacheKeys.node(this.id).interviewStage)
            ?? InterviewStage.None);
    }
    set interviewStage(value) {
        this.driver.cacheSet(cacheKeys.node(this.id).interviewStage, value);
    }
}
//# sourceMappingURL=20_Status.js.map