/**
 * @license
 * Copyright 2022-2026 Matter.js Authors
 * SPDX-License-Identifier: Apache-2.0
 */
import { MutableCluster } from "../cluster/mutation/MutableCluster.js";
import { BitFlag } from "../schema/BitmapSchema.js";
import {
  WritableFabricScopedAttribute,
  FabricScopedAttribute,
  FixedAttribute,
  Command,
  TlvNoResponse
} from "../cluster/Cluster.js";
import { TlvArray } from "../tlv/TlvArray.js";
import { TlvField, TlvObject, TlvOptionalField } from "../tlv/TlvObject.js";
import { TlvGroupId } from "../datatype/GroupId.js";
import { TlvUInt16, TlvEnum, TlvEpochUs } from "../tlv/TlvNumber.js";
import { TlvFabricIndex } from "../datatype/FabricIndex.js";
import { AccessLevel } from "#model";
import { TlvEndpointNumber } from "../datatype/EndpointNumber.js";
import { TlvString, TlvByteString } from "../tlv/TlvString.js";
import { TlvNullable } from "../tlv/TlvNullable.js";
import { TlvNoArguments } from "../tlv/TlvNoArguments.js";
import { ClusterRegistry } from "../cluster/ClusterRegistry.js";
var GroupKeyManagement;
((GroupKeyManagement2) => {
  let Feature;
  ((Feature2) => {
    Feature2["CacheAndSync"] = "CacheAndSync";
  })(Feature = GroupKeyManagement2.Feature || (GroupKeyManagement2.Feature = {}));
  GroupKeyManagement2.TlvGroupKeyMap = TlvObject({
    /**
     * This field uniquely identifies the group within the scope of the given Fabric.
     *
     * @see {@link MatterSpecification.v142.Core} § 11.2.5.3.1
     */
    groupId: TlvField(1, TlvGroupId),
    /**
     * This field references the set of group keys that generate operational group keys for use with this group, as
     * specified in Section 4.17.3.5.1, “Group Key Set ID”.
     *
     * A GroupKeyMapStruct shall NOT accept GroupKeySetID of 0, which is reserved for the IPK.
     *
     * @see {@link MatterSpecification.v142.Core} § 11.2.5.3.2
     */
    groupKeySetId: TlvField(2, TlvUInt16.bound({ min: 1 })),
    fabricIndex: TlvField(254, TlvFabricIndex)
  });
  GroupKeyManagement2.TlvGroupInfoMap = TlvObject({
    /**
     * This field uniquely identifies the group within the scope of the given Fabric.
     *
     * @see {@link MatterSpecification.v142.Core} § 11.2.5.5.1
     */
    groupId: TlvField(1, TlvGroupId),
    /**
     * This field provides the list of Endpoint IDs on the Node to which messages to this group shall be forwarded.
     *
     * @see {@link MatterSpecification.v142.Core} § 11.2.5.5.2
     */
    endpoints: TlvField(2, TlvArray(TlvEndpointNumber, { minLength: 1 })),
    /**
     * This field provides a name for the group. This field shall contain the last GroupName written for a given
     * GroupId on any Endpoint via the Groups cluster.
     *
     * @see {@link MatterSpecification.v142.Core} § 11.2.5.5.3
     */
    groupName: TlvOptionalField(3, TlvString.bound({ maxLength: 16 })),
    fabricIndex: TlvField(254, TlvFabricIndex)
  });
  let GroupKeySecurityPolicy;
  ((GroupKeySecurityPolicy2) => {
    GroupKeySecurityPolicy2[GroupKeySecurityPolicy2["TrustFirst"] = 0] = "TrustFirst";
    GroupKeySecurityPolicy2[GroupKeySecurityPolicy2["CacheAndSync"] = 1] = "CacheAndSync";
  })(GroupKeySecurityPolicy = GroupKeyManagement2.GroupKeySecurityPolicy || (GroupKeyManagement2.GroupKeySecurityPolicy = {}));
  let GroupKeyMulticastPolicy;
  ((GroupKeyMulticastPolicy2) => {
    GroupKeyMulticastPolicy2[GroupKeyMulticastPolicy2["PerGroupId"] = 0] = "PerGroupId";
    GroupKeyMulticastPolicy2[GroupKeyMulticastPolicy2["AllNodes"] = 1] = "AllNodes";
  })(GroupKeyMulticastPolicy = GroupKeyManagement2.GroupKeyMulticastPolicy || (GroupKeyManagement2.GroupKeyMulticastPolicy = {}));
  GroupKeyManagement2.TlvGroupKeySet = TlvObject({
    /**
     * This field shall provide the fabric-unique index for the associated group key set, as specified in Section
     * 4.17.3.5.1, “Group Key Set ID”.
     *
     * @see {@link MatterSpecification.v142.Core} § 11.2.5.4.1
     */
    groupKeySetId: TlvField(0, TlvUInt16),
    /**
     * This field shall provide the security policy for an operational group key set.
     *
     * When CacheAndSync is not supported in the FeatureMap of this cluster, any action attempting to set
     * CacheAndSync in the GroupKeySecurityPolicy field shall fail with an INVALID_COMMAND error.
     *
     * @see {@link MatterSpecification.v142.Core} § 11.2.5.4.2
     */
    groupKeySecurityPolicy: TlvField(1, TlvEnum()),
    /**
     * This field, if not null, shall be the root credential used in the derivation of an operational group key for
     * epoch slot 0 of the given group key set. If EpochKey0 is not null, EpochStartTime0 shall NOT be null.
     *
     * @see {@link MatterSpecification.v142.Core} § 11.2.5.4.3
     */
    epochKey0: TlvField(2, TlvNullable(TlvByteString.bound({ length: 16 }))),
    /**
     * This field, if not null, shall define when EpochKey0 becomes valid as specified by Section 4.17.3, “Epoch
     * Keys”. Units are absolute UTC time in microseconds encoded using the epoch-us representation.
     *
     * @see {@link MatterSpecification.v142.Core} § 11.2.5.4.4
     */
    epochStartTime0: TlvField(3, TlvNullable(TlvEpochUs)),
    /**
     * This field, if not null, shall be the root credential used in the derivation of an operational group key for
     * epoch slot 1 of the given group key set. If EpochKey1 is not null, EpochStartTime1 shall NOT be null.
     *
     * @see {@link MatterSpecification.v142.Core} § 11.2.5.4.5
     */
    epochKey1: TlvField(4, TlvNullable(TlvByteString.bound({ length: 16 }))),
    /**
     * This field, if not null, shall define when EpochKey1 becomes valid as specified by Section 4.17.3, “Epoch
     * Keys”. Units are absolute UTC time in microseconds encoded using the epoch-us representation.
     *
     * @see {@link MatterSpecification.v142.Core} § 11.2.5.4.6
     */
    epochStartTime1: TlvField(5, TlvNullable(TlvEpochUs)),
    /**
     * This field, if not null, shall be the root credential used in the derivation of an operational group key for
     * epoch slot 2 of the given group key set. If EpochKey2 is not null, EpochStartTime2 shall NOT be null.
     *
     * @see {@link MatterSpecification.v142.Core} § 11.2.5.4.7
     */
    epochKey2: TlvField(6, TlvNullable(TlvByteString.bound({ length: 16 }))),
    /**
     * This field, if not null, shall define when EpochKey2 becomes valid as specified by Section 4.17.3, “Epoch
     * Keys”. Units are absolute UTC time in microseconds encoded using the epoch-us representation.
     *
     * @see {@link MatterSpecification.v142.Core} § 11.2.5.4.8
     */
    epochStartTime2: TlvField(7, TlvNullable(TlvEpochUs)),
    /**
     * This field specifies how the IPv6 Multicast Address shall be formed for groups using this operational group
     * key set.
     *
     * The PerGroupID method maximizes filtering of multicast messages, so that receiving nodes receive only
     * multicast messages for groups to which they are subscribed.
     *
     * The AllNodes method minimizes the number of multicast addresses to which a receiver node needs to subscribe.
     *
     * > [!NOTE]
     *
     * > Support for GroupKeyMulticastPolicy is provisional. Correct default behavior is that implied by value
     *   PerGroupID.
     *
     * @see {@link MatterSpecification.v142.Core} § 11.2.5.4.9
     */
    groupKeyMulticastPolicy: TlvOptionalField(8, TlvEnum())
  });
  GroupKeyManagement2.TlvKeySetWriteRequest = TlvObject({ groupKeySet: TlvField(0, GroupKeyManagement2.TlvGroupKeySet) });
  GroupKeyManagement2.TlvKeySetReadRequest = TlvObject({ groupKeySetId: TlvField(0, TlvUInt16) });
  GroupKeyManagement2.TlvKeySetReadResponse = TlvObject({ groupKeySet: TlvField(0, GroupKeyManagement2.TlvGroupKeySet) });
  GroupKeyManagement2.TlvKeySetRemoveRequest = TlvObject({ groupKeySetId: TlvField(0, TlvUInt16) });
  GroupKeyManagement2.TlvKeySetReadAllIndicesResponse = TlvObject({
    /**
     * This field references the set of group keys that generate operational group keys for use with the accessing
     * fabric.
     *
     * Each entry in GroupKeySetIDs is a GroupKeySetID field.
     *
     * @see {@link MatterSpecification.v142.Core} § 11.2.7.6.1
     */
    groupKeySetIDs: TlvField(0, TlvArray(TlvUInt16))
  });
  GroupKeyManagement2.Base = MutableCluster.Component({
    id: 63,
    name: "GroupKeyManagement",
    revision: 2,
    features: {
      /**
       * The ability to support CacheAndSync security policy and MCSP.
       */
      cacheAndSync: BitFlag(0)
    },
    attributes: {
      /**
       * This attribute is a list of GroupKeyMapStruct entries. Each entry associates a logical Group Id with a
       * particular group key set.
       *
       * @see {@link MatterSpecification.v142.Core} § 11.2.6.1
       */
      groupKeyMap: WritableFabricScopedAttribute(
        0,
        TlvArray(GroupKeyManagement2.TlvGroupKeyMap),
        { persistent: true, default: [], writeAcl: AccessLevel.Manage }
      ),
      /**
       * This attribute is a list of GroupInfoMapStruct entries. Each entry provides read-only information about
       * how a given logical Group ID maps to a particular set of endpoints, and a name for the group.
       *
       * The content of this attribute reflects data managed via the Groups cluster (see AppClusters), and is in
       * general terms referred to as the 'node-wide Group Table'.
       *
       * The GroupTable shall NOT contain any entry whose GroupInfoMapStruct has an empty Endpoints list. If a
       * RemoveGroup or RemoveAllGroups command causes the removal of a group mapping from its last mapped
       * endpoint, the entire GroupTable entry for that given GroupId shall be removed.
       *
       * @see {@link MatterSpecification.v142.Core} § 11.2.6.2
       */
      groupTable: FabricScopedAttribute(1, TlvArray(GroupKeyManagement2.TlvGroupInfoMap), { default: [] }),
      /**
       * Indicates the maximum number of groups that this node supports per fabric. The value of this attribute
       * shall be set to be no less than the required minimum supported groups as specified in Section 2.11.1.2,
       * “Group Limits”. The length of the GroupKeyMap and GroupTable list attributes shall NOT exceed the value
       * of the MaxGroupsPerFabric attribute multiplied by the number of supported fabrics.
       *
       * @see {@link MatterSpecification.v142.Core} § 11.2.6.3
       */
      maxGroupsPerFabric: FixedAttribute(2, TlvUInt16, { default: 0 }),
      /**
       * Indicates the maximum number of group key sets this node supports per fabric. The value of this attribute
       * shall be set according to the minimum number of group key sets to support as specified in Section
       * 2.11.1.2, “Group Limits”.
       *
       * @see {@link MatterSpecification.v142.Core} § 11.2.6.4
       */
      maxGroupKeysPerFabric: FixedAttribute(3, TlvUInt16.bound({ min: 1 }), { default: 1 })
    },
    commands: {
      /**
       * This command is used by Administrators to set the state of a given Group Key Set, including atomically
       * updating the state of all epoch keys.
       *
       * ### Effect on Receipt
       *
       * The following validations shall be done against the content of the GroupKeySet field:
       *
       *   • If the EpochKey0 field is null or its associated EpochStartTime0 field is null, then this command
       *     shall fail with an INVALID_COMMAND status code responded to the client.
       *
       *   • If the EpochKey0 field’s length is not exactly 16 bytes, then this command shall fail with a
       *     CONSTRAINT_ERROR status code responded to the client.
       *
       *   • If the EpochStartTime0 is set to 0, then this command shall fail with an INVALID_COMMAND status code
       *     responded to the client. Note that internally, a GroupKeySetStruct’s EpochStartTime0 may be set to
       *     zero, due to the behavior of the AddNOC command which synthesizes a GroupKeySetStruct (see Section
       *     11.18.6.8.1, “IPKValue Field”). However, the value 0 is illegal in the GroupKeySet field sent by a
       *     client.
       *
       *   • If the EpochKey1 field is not null, then the EpochKey0 field shall NOT be null. Otherwise this
       *     command shall fail with an INVALID_COMMAND status code responded to the client.
       *
       *   • If the EpochKey1 field is not null, and the field’s length is not exactly 16 bytes, then this command
       *     shall fail with a CONSTRAINT_ERROR status code responded to the client.
       *
       *   • If the EpochKey1 field is not null, its associated EpochStartTime1 field shall NOT be null and shall
       *     contain a later epoch start time than the epoch start time found in the EpochStartTime0 field.
       *     Otherwise this command shall fail with an INVALID_COMMAND status code responded to the client.
       *
       *   • If exactly one of the EpochKey1 or EpochStartTime1 is null, rather than both being null, or neither
       *     being null, then this command shall fail with an INVALID_COMMAND status code responded to the client.
       *
       *   • If the EpochKey2 field is not null, then the EpochKey1 and EpochKey0 fields shall NOT be null.
       *     Otherwise this command shall fail with an INVALID_COMMAND status code responded to the client.
       *
       *   • If the EpochKey2 field is not null, and the field’s length is not exactly 16 bytes, then this command
       *     shall fail with a CONSTRAINT_ERROR status code responded to the client.
       *
       *   • If the EpochKey2 field is not null, its associated EpochStartTime2 field shall NOT be null and shall
       *     contain a later epoch start time than the epoch start time found in the EpochStartTime1 field.
       *     Otherwise this command shall fail with an INVALID_COMMAND status code responded to the client.
       *
       *   • If exactly one of the EpochKey2 or EpochStartTime2 is null, rather than both being null, or neither
       *     being null, then this command shall fail with an INVALID_COMMAND status code responded to the client.
       *
       * If there exists a Group Key Set associated with the accessing fabric which has the same GroupKeySetID as
       * that provided in the GroupKeySet field, then the contents of that group key set shall be replaced. A
       * replacement shall be done by executing the equivalent of entirely removing the previous Group Key Set
       * with the given GroupKeySetID, followed by an addition of a Group Key Set with the provided configuration.
       * Otherwise, if the GroupKeySetID did not match an existing entry, a new Group Key Set associated with the
       * accessing fabric shall be created with the provided data. The Group Key Set shall be written to
       * non-volatile storage.
       *
       * Upon completion, this command shall send a status code back to the initiator:
       *
       *   • If the Group Key Set was properly installed or updated on the Node, the status code shall be set to
       *     SUCCESS.
       *
       *   • If there are insufficient resources on the receiver to store an additional Group Key Set, the status
       *     code shall be set to RESOURCE_EXHAUSTED (see Section 2.11.1.2, “Group Limits”);
       *
       *   • Otherwise, this status code shall be set to FAILURE.
       *
       * @see {@link MatterSpecification.v142.Core} § 11.2.7.1
       */
      keySetWrite: Command(0, GroupKeyManagement2.TlvKeySetWriteRequest, 0, TlvNoResponse, { invokeAcl: AccessLevel.Administer }),
      /**
       * This command is used by Administrators to read the state of a given Group Key Set.
       *
       * ### Effect on Receipt
       *
       * If there exists a Group Key Set associated with the accessing fabric which has the same GroupKeySetID as
       * that provided in the GroupKeySetID field, then the contents of that Group Key Set shall be sent in a
       * KeySetReadResponse command, but with the EpochKey0, EpochKey1 and EpochKey2 fields replaced by null.
       *
       * Otherwise, if the GroupKeySetID does not refer to a Group Key Set associated with the accessing fabric,
       * then this command shall fail with a NOT_FOUND status code.
       *
       * @see {@link MatterSpecification.v142.Core} § 11.2.7.2
       */
      keySetRead: Command(
        1,
        GroupKeyManagement2.TlvKeySetReadRequest,
        2,
        GroupKeyManagement2.TlvKeySetReadResponse,
        { invokeAcl: AccessLevel.Administer }
      ),
      /**
       * This command is used by Administrators to remove all state of a given Group Key Set.
       *
       * ### Effect on Receipt
       *
       * If there exists a Group Key Set associated with the accessing fabric which has the same GroupKeySetID as
       * that provided in the GroupKeySetID field, then the contents of that Group Key Set shall be removed,
       * including all epoch keys it contains.
       *
       * If there exist any entries for the accessing fabric within the GroupKeyMap attribute that refer to the
       * GroupKeySetID just removed, then these entries shall be removed from that list.
       *
       * This command shall fail with an INVALID_COMMAND status code back to the initiator if the GroupKeySetID
       * being removed is 0, which is the Key Set associated with the Identity Protection Key (IPK). The only
       * method to remove the IPK is usage of the RemoveFabric command or any operation which causes the
       * equivalent of a RemoveFabric to occur by side-effect.
       *
       * This command shall send a SUCCESS status code back to the initiator on success, or NOT_FOUND if the
       * GroupKeySetID requested did not exist.
       *
       * @see {@link MatterSpecification.v142.Core} § 11.2.7.4
       */
      keySetRemove: Command(
        3,
        GroupKeyManagement2.TlvKeySetRemoveRequest,
        3,
        TlvNoResponse,
        { invokeAcl: AccessLevel.Administer }
      ),
      /**
       * This command is used by Administrators to query a list of all Group Key Sets associated with the
       * accessing fabric.
       *
       * ### Effect on Receipt
       *
       * Upon receipt, this command shall iterate all stored GroupKeySetStruct associated with the accessing
       * fabric and generate a KeySetReadAllIndicesResponse command containing the list of GroupKeySetID values
       * from those structs.
       *
       * @see {@link MatterSpecification.v142.Core} § 11.2.7.5
       */
      keySetReadAllIndices: Command(
        4,
        TlvNoArguments,
        5,
        GroupKeyManagement2.TlvKeySetReadAllIndicesResponse,
        { invokeAcl: AccessLevel.Administer }
      )
    },
    /**
     * This metadata controls which GroupKeyManagementCluster elements matter.js activates for specific feature
     * combinations.
     */
    extensions: MutableCluster.Extensions()
  });
  GroupKeyManagement2.ClusterInstance = MutableCluster(GroupKeyManagement2.Base);
  GroupKeyManagement2.Cluster = GroupKeyManagement2.ClusterInstance;
  GroupKeyManagement2.Complete = GroupKeyManagement2.Cluster;
})(GroupKeyManagement || (GroupKeyManagement = {}));
const GroupKeyManagementCluster = GroupKeyManagement.Cluster;
ClusterRegistry.register(GroupKeyManagement.Complete);
export {
  GroupKeyManagement,
  GroupKeyManagementCluster
};
//# sourceMappingURL=group-key-management.js.map
