/**
 * @license
 * Copyright 2022-2024 Matter.js Authors
 * SPDX-License-Identifier: Apache-2.0
 */
import { GeneralDiagnosticsBehavior } from "#behaviors/general-diagnostics";
import { GeneralDiagnostics } from "#clusters/general-diagnostics";
import { OnOff } from "#clusters/on-off";
import { RootEndpoint } from "#endpoints/root";
import { Time } from "#general";
import { OnOffBehavior } from "./OnOffBehavior.js";
const Base = OnOffBehavior.with(OnOff.Feature.Lighting);
class OnOffServer extends Base {
  initialize() {
    if (this.features.lighting && this.#getBootReason() !== GeneralDiagnostics.BootReason.SoftwareUpdateCompleted) {
      const startUpOnOffValue = this.state.startUpOnOff ?? null;
      const currentOnOffStatus = this.state.onOff;
      if (startUpOnOffValue !== null) {
        const targetOnOffValue = startUpOnOffValue === OnOff.StartUpOnOff.Toggle ? !currentOnOffStatus : startUpOnOffValue === OnOff.StartUpOnOff.On;
        if (targetOnOffValue !== currentOnOffStatus) {
          this.state.onOff = targetOnOffValue;
        }
      }
    }
  }
  async [Symbol.asyncDispose]() {
    this.internal.timedOnTimer?.stop();
    this.internal.delayedOffTimer?.stop();
    await super[Symbol.asyncDispose]?.();
  }
  on() {
    this.state.onOff = true;
    if (this.features.lighting) {
      if (!this.timedOnTimer.isRunning) {
        if (this.delayedOffTimer.isRunning) {
          this.delayedOffTimer.stop();
        }
        this.state.offWaitTime = 0;
      }
    }
  }
  off() {
    this.state.onOff = false;
    if (this.features.lighting) {
      if (this.timedOnTimer.isRunning) {
        this.timedOnTimer.stop();
        if ((this.state.offWaitTime ?? 0) > 0) {
          this.delayedOffTimer.start();
        }
      }
      this.state.onTime = 0;
    }
  }
  /**
   * Default implementation notes:
   * This method uses the on/off methods when timed actions should occur. This means that it is enough to override
   * on() and off() with custom control logic.
   */
  toggle() {
    if (this.state.onOff) {
      return this.off();
    } else {
      return this.on();
    }
  }
  /**
   * Default implementation notes:
   * * This implementation ignores the effect and just calls off().
   * * Global Scene Control is not supported yet.
   */
  offWithEffect() {
    if (this.state.globalSceneControl) {
      this.state.globalSceneControl = false;
    }
    return this.off();
  }
  /**
   * Default implementation notes:
   * * Global Scene Control is not supported yet, so the device is just turned on.
   */
  onWithRecallGlobalScene() {
    if (this.state.globalSceneControl) {
      return;
    }
    this.state.globalSceneControl = true;
    if (this.state.onTime === 0) {
      this.state.offWaitTime = 0;
    }
    return this.on();
  }
  /**
   * Default implementation notes:
   * * This method uses the on/off methods when timed actions should occur. This means that it is enough to override
   * on() and off() with custom control logic.
   */
  onWithTimedOff({ onOffControl, offWaitTime, onTime }) {
    if (onOffControl.acceptOnlyWhenOn && !this.state.onOff) {
      return;
    }
    if (this.delayedOffTimer.isRunning && !this.state.onOff) {
      this.state.offWaitTime = Math.min(offWaitTime ?? 0, this.state.offWaitTime ?? 0);
      return;
    }
    this.state.onTime = Math.max(onTime ?? 0, this.state.onTime ?? 0);
    this.state.offWaitTime = offWaitTime;
    if (this.state.onTime !== 0 && this.state.offWaitTime !== 0) {
      this.timedOnTimer.start();
    }
    return this.on();
  }
  get timedOnTimer() {
    let timer = this.internal.timedOnTimer;
    if (timer === void 0) {
      timer = this.internal.timedOnTimer = Time.getPeriodicTimer(
        "Timed on",
        100,
        this.callback(this.#timedOnTick)
      );
    }
    return timer;
  }
  async #timedOnTick() {
    let time = (this.state.onTime ?? 0) - 1;
    if (time <= 0) {
      time = 0;
      this.internal.timedOnTimer?.stop();
      this.state.offWaitTime = 0;
      await this.off();
    }
    this.state.onTime = time;
  }
  get delayedOffTimer() {
    let timer = this.internal.delayedOffTimer;
    if (timer === void 0) {
      timer = this.internal.delayedOffTimer = Time.getTimer(
        "Delayed off",
        100,
        this.callback(this.#delayedOffTick)
      );
    }
    return timer;
  }
  #delayedOffTick() {
    let time = (this.state.offWaitTime ?? 0) - 1;
    if (time <= 0) {
      time = 0;
      this.internal.delayedOffTimer?.stop();
    }
    this.state.offWaitTime = time;
  }
  #getBootReason() {
    const rootEndpoint = this.endpoint.ownerOfType(RootEndpoint);
    if (rootEndpoint !== void 0 && rootEndpoint.behaviors.has(GeneralDiagnosticsBehavior)) {
      return rootEndpoint.stateOf(GeneralDiagnosticsBehavior).bootReason;
    }
  }
}
((OnOffServer2) => {
  class Internal {
    timedOnTimer;
    delayedOffTimer;
  }
  OnOffServer2.Internal = Internal;
})(OnOffServer || (OnOffServer = {}));
export {
  OnOffServer
};
//# sourceMappingURL=OnOffServer.js.map
