/**
 * @license
 * Copyright 2022-2026 Matter.js Authors
 * SPDX-License-Identifier: Apache-2.0
 */
import { Logger, MatterFlowError, Time } from "@matter/general";
class MatterFabricConflictError extends MatterFlowError {
}
const logger = Logger.get("FailsafeTimer");
class FailsafeTimer {
  constructor(associatedFabric, expiryLength, maxCumulativeFailsafe, expiryCallback) {
    this.associatedFabric = associatedFabric;
    this.#expiryCallback = expiryCallback;
    this.#failsafeTimer = this.#startFailsafeTimer(expiryLength);
    this.#maxCumulativeFailsafeTimer = Time.getTimer(
      "Max cumulative failsafe",
      maxCumulativeFailsafe,
      () => this.expire()
    ).start();
  }
  #expiryCallback;
  #failsafeTimer;
  #maxCumulativeFailsafeTimer;
  #completed = false;
  async close() {
    if (this.#failsafeTimer.isRunning) {
      this.#failsafeTimer.stop();
    }
    if (this.#maxCumulativeFailsafeTimer.isRunning) {
      this.#maxCumulativeFailsafeTimer.stop();
    }
  }
  /** Handle "Re-Arming" an existing FailSafe context to extend the timer, expire or fail if not allowed. */
  async reArm(associatedFabric, expiry, currentExchange) {
    if (!this.#failsafeTimer.isRunning) {
      throw new MatterFlowError("FailSafe already expired.");
    }
    if (this.associatedFabric?.fabricIndex !== associatedFabric?.fabricIndex) {
      throw new MatterFlowError(
        `FailSafe already armed (index=${this.associatedFabric?.fabricIndex}) with different fabric (index=${associatedFabric?.fabricIndex}).`
      );
    }
    this.#failsafeTimer.stop();
    if (expiry === 0) {
      await this.expire(currentExchange);
    } else {
      this.#failsafeTimer = this.#startFailsafeTimer(expiry);
    }
  }
  /** Returns whether the FailSafe context is currently armed. */
  get completed() {
    return this.#completed;
  }
  /** Expire the FailSafe context. This is called by the timer and can also be called manually if needed. */
  async expire(currentExchange) {
    if (this.#completed) {
      return;
    }
    this.complete();
    await this.#expiryCallback(currentExchange);
  }
  /** Complete the FailSafe context. This is called when the commissioning is completed. */
  complete() {
    this.#completed = true;
    this.#failsafeTimer.stop();
    this.#maxCumulativeFailsafeTimer.stop();
  }
  #startFailsafeTimer(expiry) {
    return Time.getTimer(
      "Failsafe expiration",
      expiry,
      () => this.expire().catch((e) => logger.error("Error during failsafe expiration", e))
    ).start();
  }
}
export {
  FailsafeTimer,
  MatterFabricConflictError
};
//# sourceMappingURL=FailsafeTimer.js.map
