/**
 * @license
 * Copyright 2022-2026 Matter.js Authors
 * SPDX-License-Identifier: Apache-2.0
 */
import { MutableCluster } from "../cluster/mutation/MutableCluster.js";
import {
  OptionalWritableAttribute,
  Attribute,
  FixedAttribute,
  OptionalFixedAttribute,
  OptionalEvent
} from "../cluster/Cluster.js";
import { TlvUInt16, TlvUInt8, TlvBitmap, TlvEnum } from "../tlv/TlvNumber.js";
import { AccessLevel } from "#model";
import { BitFlag } from "../schema/BitmapSchema.js";
import { TlvField, TlvObject } from "../tlv/TlvObject.js";
import { Priority } from "../globals/Priority.js";
import { ClusterRegistry } from "../cluster/ClusterRegistry.js";
var OccupancySensing;
((OccupancySensing2) => {
  let Feature;
  ((Feature2) => {
    Feature2["Other"] = "Other";
    Feature2["PassiveInfrared"] = "PassiveInfrared";
    Feature2["Ultrasonic"] = "Ultrasonic";
    Feature2["PhysicalContact"] = "PhysicalContact";
    Feature2["ActiveInfrared"] = "ActiveInfrared";
    Feature2["Radar"] = "Radar";
    Feature2["RfSensing"] = "RfSensing";
    Feature2["Vision"] = "Vision";
  })(Feature = OccupancySensing2.Feature || (OccupancySensing2.Feature = {}));
  OccupancySensing2.Occupancy = {
    /**
     * Indicates the sensed occupancy state
     *
     * If this bit is set, it shall indicate the occupied state else if the bit if not set, it shall indicate the
     * unoccupied state.
     *
     * @see {@link MatterSpecification.v142.Cluster} § 2.7.5.1.1
     */
    occupied: BitFlag(0)
  };
  let OccupancySensorType;
  ((OccupancySensorType2) => {
    OccupancySensorType2[OccupancySensorType2["Pir"] = 0] = "Pir";
    OccupancySensorType2[OccupancySensorType2["Ultrasonic"] = 1] = "Ultrasonic";
    OccupancySensorType2[OccupancySensorType2["PirAndUltrasonic"] = 2] = "PirAndUltrasonic";
    OccupancySensorType2[OccupancySensorType2["PhysicalContact"] = 3] = "PhysicalContact";
  })(OccupancySensorType = OccupancySensing2.OccupancySensorType || (OccupancySensing2.OccupancySensorType = {}));
  OccupancySensing2.OccupancySensorTypeBitmap = {
    /**
     * Indicates a passive infrared sensor.
     */
    pir: BitFlag(0),
    /**
     * Indicates a ultrasonic sensor.
     */
    ultrasonic: BitFlag(1),
    /**
     * Indicates a physical contact sensor.
     */
    physicalContact: BitFlag(2)
  };
  OccupancySensing2.TlvHoldTimeLimits = TlvObject({
    /**
     * This field shall specify the minimum value of the server’s supported value for the HoldTime attribute, in
     * seconds.
     *
     * @see {@link MatterSpecification.v142.Cluster} § 2.7.5.4.1
     */
    holdTimeMin: TlvField(0, TlvUInt16.bound({ min: 1 })),
    /**
     * This field shall specify the maximum value of the server’s supported value for the HoldTime attribute, in
     * seconds.
     *
     * @see {@link MatterSpecification.v142.Cluster} § 2.7.5.4.2
     */
    holdTimeMax: TlvField(1, TlvUInt16),
    /**
     * This field shall specify the (manufacturer-determined) default value of the server’s HoldTime attribute, in
     * seconds. This is the value that a client who wants to reset the settings to a valid default SHOULD use.
     *
     * @see {@link MatterSpecification.v142.Cluster} § 2.7.5.4.3
     */
    holdTimeDefault: TlvField(2, TlvUInt16)
  });
  OccupancySensing2.TlvOccupancyChangedEvent = TlvObject({
    /**
     * This field shall indicate the new value of the Occupancy attribute.
     *
     * @see {@link MatterSpecification.v142.Cluster} § 2.7.7.1.1
     */
    occupancy: TlvField(0, TlvBitmap(TlvUInt8, OccupancySensing2.Occupancy))
  });
  OccupancySensing2.PassiveInfraredComponent = MutableCluster.Component({
    attributes: {
      /**
       * This attribute shall specify the time delay, in seconds, before the PIR sensor changes to its unoccupied
       * state after the last detection of occupancy in the sensed area.
       *
       * @see {@link MatterSpecification.v142.Cluster} § 2.7.6.6
       */
      pirOccupiedToUnoccupiedDelay: OptionalWritableAttribute(
        16,
        TlvUInt16,
        { persistent: true, default: 0, writeAcl: AccessLevel.Manage }
      ),
      /**
       * This attribute shall specify the time delay, in seconds, before the PIR sensor changes to its occupied
       * state after the first detection of occupancy in the sensed area.
       *
       * @see {@link MatterSpecification.v142.Cluster} § 2.7.6.7
       */
      pirUnoccupiedToOccupiedDelay: OptionalWritableAttribute(
        17,
        TlvUInt16,
        { persistent: true, default: 0, writeAcl: AccessLevel.Manage }
      ),
      /**
       * This attribute shall specify the number of occupancy detection events that must occur in the period
       * PIRUnoccupiedToOccupiedDelay, before the PIR sensor changes to its occupied state.
       *
       * @see {@link MatterSpecification.v142.Cluster} § 2.7.6.8
       */
      pirUnoccupiedToOccupiedThreshold: OptionalWritableAttribute(
        18,
        TlvUInt8.bound({ min: 1, max: 254 }),
        { persistent: true, default: 1, writeAcl: AccessLevel.Manage }
      )
    }
  });
  OccupancySensing2.UltrasonicComponent = MutableCluster.Component({
    attributes: {
      /**
       * This attribute shall specify the time delay, in seconds, before the Ultrasonic sensor changes to its
       * unoccupied state after the last detection of occupancy in the sensed area.
       *
       * @see {@link MatterSpecification.v142.Cluster} § 2.7.6.9
       */
      ultrasonicOccupiedToUnoccupiedDelay: OptionalWritableAttribute(
        32,
        TlvUInt16,
        { persistent: true, default: 0, writeAcl: AccessLevel.Manage }
      ),
      /**
       * This attribute shall specify the time delay, in seconds, before the Ultrasonic sensor changes to its
       * occupied state after the first detection of occupancy in the sensed area.
       *
       * @see {@link MatterSpecification.v142.Cluster} § 2.7.6.10
       */
      ultrasonicUnoccupiedToOccupiedDelay: OptionalWritableAttribute(
        33,
        TlvUInt16,
        { persistent: true, default: 0, writeAcl: AccessLevel.Manage }
      ),
      /**
       * This attribute shall specify the number of occupancy detection events that must occur in the period
       * UltrasonicUnoccupiedToOccupiedDelay, before the Ultrasonic sensor changes to its occupied state.
       *
       * @see {@link MatterSpecification.v142.Cluster} § 2.7.6.11
       */
      ultrasonicUnoccupiedToOccupiedThreshold: OptionalWritableAttribute(
        34,
        TlvUInt8.bound({ min: 1, max: 254 }),
        { persistent: true, default: 1, writeAcl: AccessLevel.Manage }
      )
    }
  });
  OccupancySensing2.PhysicalContactComponent = MutableCluster.Component({
    attributes: {
      /**
       * This attribute shall specify the time delay, in seconds, before the physical contact occupancy sensor
       * changes to its unoccupied state after detecting the unoccupied event.
       *
       * @see {@link MatterSpecification.v142.Cluster} § 2.7.6.12
       */
      physicalContactOccupiedToUnoccupiedDelay: OptionalWritableAttribute(
        48,
        TlvUInt16,
        { persistent: true, default: 0, writeAcl: AccessLevel.Manage }
      ),
      /**
       * This attribute shall specify the time delay, in seconds, before the physical contact sensor changes to
       * its occupied state after the first detection of the occupied event.
       *
       * @see {@link MatterSpecification.v142.Cluster} § 2.7.6.13
       */
      physicalContactUnoccupiedToOccupiedDelay: OptionalWritableAttribute(
        49,
        TlvUInt16,
        { persistent: true, default: 0, writeAcl: AccessLevel.Manage }
      ),
      /**
       * This attribute shall specify the number of occupancy detection events that must occur in the period
       * PhysicalContactUnoccupiedToOccupiedDelay, before the PhysicalContact sensor changes to its occupied
       * state.
       *
       * @see {@link MatterSpecification.v142.Cluster} § 2.7.6.14
       */
      physicalContactUnoccupiedToOccupiedThreshold: OptionalWritableAttribute(
        50,
        TlvUInt8.bound({ min: 1, max: 254 }),
        { persistent: true, default: 1, writeAcl: AccessLevel.Manage }
      )
    }
  });
  OccupancySensing2.Base = MutableCluster.Component({
    id: 1030,
    name: "OccupancySensing",
    revision: 5,
    features: {
      /**
       * Supports sensing using a modality not listed in the other bits
       */
      other: BitFlag(0),
      /**
       * Supports sensing using PIR (Passive InfraRed)
       */
      passiveInfrared: BitFlag(1),
      /**
       * Supports sensing using UltraSound
       */
      ultrasonic: BitFlag(2),
      /**
       * Supports sensing using a physical contact
       */
      physicalContact: BitFlag(3),
      /**
       * Supports sensing using Active InfraRed measurement (e.g. time-of-flight or transflective/reflective IR
       * sensing)
       */
      activeInfrared: BitFlag(4),
      /**
       * Supports sensing using radar waves (microwave)
       */
      radar: BitFlag(5),
      /**
       * Supports sensing using analysis of radio signals, e.g.: RSSI, CSI and/or any other metric from the signal
       */
      rfSensing: BitFlag(6),
      /**
       * Supports sensing based on analyzing images
       */
      vision: BitFlag(7)
    },
    attributes: {
      /**
       * Indicates the sensed (processed) status of occupancy. For compatibility reasons this is expressed as a
       * bitmap where the status is indicated in bit 0: a value of 1 means occupied, and 0 means unoccupied, with
       * the other bits set to 0; this can be considered equivalent to a boolean.
       *
       * @see {@link MatterSpecification.v142.Cluster} § 2.7.6.1
       */
      occupancy: Attribute(0, TlvBitmap(TlvUInt8, OccupancySensing2.Occupancy)),
      /**
       * @see {@link MatterSpecification.v142.Cluster} § 2.7.6
       */
      occupancySensorType: FixedAttribute(1, TlvEnum()),
      /**
       * @see {@link MatterSpecification.v142.Cluster} § 2.7.6
       */
      occupancySensorTypeBitmap: FixedAttribute(2, TlvBitmap(TlvUInt8, OccupancySensing2.OccupancySensorTypeBitmap)),
      /**
       * This attribute shall specify the time delay, in seconds, before the sensor changes to its unoccupied
       * state after the last detection of occupancy in the sensed area. This is equivalent to the legacy
       * *OccupiedToUnoccupiedDelay attributes.
       *
       * Low values of HoldTime SHOULD be avoided since they could lead to many reporting messages. A value 0 for
       * HoldTime shall NOT be used.
       *
       * The figure below illustrates this with an example of how this attribute is used for a PIR sensor. It uses
       * threshold detection to generate an "internal detection" signal, which needs post-processing to become
       * usable for transmission (traffic shaping). The bit in the Occupancy attribute will be set to 1 when the
       * internal detection signal goes high, and will stay at 1 for HoldTime after the (last) instance where the
       * internal detection signal goes low.
       *
       * The top half of the figure shows the case of a single trigger: the bit in the Occupancy attribute will be
       * 1 for the duration of the PIR signal exceeding the threshold plus HoldTime. The bottom half of the figure
       * shows the case of multiple triggers: the second trigger starts before the HoldTime of the first trigger
       * has expired; this results in a single period of the bit in the Occupancy attribute being 1. The bit in
       * the Occupancy attribute will be set to 1 from the start of the first period where the PIR signal exceeds
       * the threshold until HoldTime after the last moment where the PIR exceeded the threshold.
       *
       * @see {@link MatterSpecification.v142.Cluster} § 2.7.6.3
       */
      holdTime: OptionalWritableAttribute(3, TlvUInt16, { persistent: true, writeAcl: AccessLevel.Manage }),
      /**
       * Indicates the server’s limits, and default value, for the HoldTime attribute.
       *
       * @see {@link MatterSpecification.v142.Cluster} § 2.7.6.4
       */
      holdTimeLimits: OptionalFixedAttribute(4, OccupancySensing2.TlvHoldTimeLimits)
    },
    events: {
      /**
       * If this event is supported, it shall be generated when the Occupancy attribute changes.
       *
       * @see {@link MatterSpecification.v142.Cluster} § 2.7.7.1
       */
      occupancyChanged: OptionalEvent(0, Priority.Info, OccupancySensing2.TlvOccupancyChangedEvent)
    },
    /**
     * This metadata controls which OccupancySensingCluster elements matter.js activates for specific feature
     * combinations.
     */
    extensions: MutableCluster.Extensions(
      { flags: { passiveInfrared: true }, component: OccupancySensing2.PassiveInfraredComponent },
      { flags: { ultrasonic: true }, component: OccupancySensing2.UltrasonicComponent },
      { flags: { physicalContact: true }, component: OccupancySensing2.PhysicalContactComponent },
      {
        flags: {
          other: false,
          passiveInfrared: false,
          ultrasonic: false,
          physicalContact: false,
          activeInfrared: false,
          radar: false,
          rfSensing: false,
          vision: false
        },
        component: false
      }
    )
  });
  OccupancySensing2.ClusterInstance = MutableCluster.ExtensibleOnly(OccupancySensing2.Base);
  OccupancySensing2.Cluster = OccupancySensing2.ClusterInstance;
  const PIR = { passiveInfrared: true };
  const US = { ultrasonic: true };
  const PHY = { physicalContact: true };
  OccupancySensing2.CompleteInstance = MutableCluster({
    id: OccupancySensing2.Base.id,
    name: OccupancySensing2.Base.name,
    revision: OccupancySensing2.Base.revision,
    features: OccupancySensing2.Base.features,
    attributes: {
      ...OccupancySensing2.Base.attributes,
      pirOccupiedToUnoccupiedDelay: MutableCluster.AsConditional(
        OccupancySensing2.PassiveInfraredComponent.attributes.pirOccupiedToUnoccupiedDelay,
        { optionalIf: [PIR] }
      ),
      pirUnoccupiedToOccupiedDelay: MutableCluster.AsConditional(
        OccupancySensing2.PassiveInfraredComponent.attributes.pirUnoccupiedToOccupiedDelay,
        { optionalIf: [PIR] }
      ),
      pirUnoccupiedToOccupiedThreshold: MutableCluster.AsConditional(
        OccupancySensing2.PassiveInfraredComponent.attributes.pirUnoccupiedToOccupiedThreshold,
        { optionalIf: [PIR] }
      ),
      ultrasonicOccupiedToUnoccupiedDelay: MutableCluster.AsConditional(
        OccupancySensing2.UltrasonicComponent.attributes.ultrasonicOccupiedToUnoccupiedDelay,
        { optionalIf: [US] }
      ),
      ultrasonicUnoccupiedToOccupiedDelay: MutableCluster.AsConditional(
        OccupancySensing2.UltrasonicComponent.attributes.ultrasonicUnoccupiedToOccupiedDelay,
        { optionalIf: [US] }
      ),
      ultrasonicUnoccupiedToOccupiedThreshold: MutableCluster.AsConditional(
        OccupancySensing2.UltrasonicComponent.attributes.ultrasonicUnoccupiedToOccupiedThreshold,
        { optionalIf: [US] }
      ),
      physicalContactOccupiedToUnoccupiedDelay: MutableCluster.AsConditional(
        OccupancySensing2.PhysicalContactComponent.attributes.physicalContactOccupiedToUnoccupiedDelay,
        { optionalIf: [PHY] }
      ),
      physicalContactUnoccupiedToOccupiedDelay: MutableCluster.AsConditional(
        OccupancySensing2.PhysicalContactComponent.attributes.physicalContactUnoccupiedToOccupiedDelay,
        { optionalIf: [PHY] }
      ),
      physicalContactUnoccupiedToOccupiedThreshold: MutableCluster.AsConditional(
        OccupancySensing2.PhysicalContactComponent.attributes.physicalContactUnoccupiedToOccupiedThreshold,
        { optionalIf: [PHY] }
      )
    },
    events: OccupancySensing2.Base.events
  });
  OccupancySensing2.Complete = OccupancySensing2.CompleteInstance;
})(OccupancySensing || (OccupancySensing = {}));
const OccupancySensingCluster = OccupancySensing.Cluster;
ClusterRegistry.register(OccupancySensing.Complete);
export {
  OccupancySensing,
  OccupancySensingCluster
};
//# sourceMappingURL=occupancy-sensing.js.map
