/**
 * @license
 * Copyright 2022-2025 Matter.js Authors
 * SPDX-License-Identifier: Apache-2.0
 */
import { MutableCluster } from "../cluster/mutation/MutableCluster.js";
import { BitFlag } from "../schema/BitmapSchema.js";
import { FixedAttribute, Command, TlvNoResponse } from "../cluster/Cluster.js";
import { TlvUInt8, TlvBitmap, TlvEnum } from "../tlv/TlvNumber.js";
import { TlvField, TlvObject } from "../tlv/TlvObject.js";
import { TlvGroupId } from "../datatype/GroupId.js";
import { TlvString } from "../tlv/TlvString.js";
import { AccessLevel } from "#model";
import { TlvArray } from "../tlv/TlvArray.js";
import { TlvNullable } from "../tlv/TlvNullable.js";
import { TlvNoArguments } from "../tlv/TlvNoArguments.js";
import { ClusterRegistry } from "../cluster/ClusterRegistry.js";
var Groups;
((Groups2) => {
  let Feature;
  ((Feature2) => {
    Feature2["GroupNames"] = "GroupNames";
  })(Feature = Groups2.Feature || (Groups2.Feature = {}));
  Groups2.NameSupportAttribute = { groupNames: BitFlag(7) };
  Groups2.TlvAddGroupRequest = TlvObject({
    /**
     * This field shall be used to identify the group and any associated key material to which the server endpoint
     * is to be added.
     *
     * @see {@link MatterSpecification.v142.Cluster} § 1.3.7.1.1
     */
    groupId: TlvField(0, TlvGroupId),
    /**
     * This field may be set to a human-readable name for the group. If the client has no name for the group, the
     * GroupName field shall be set to the empty string.
     *
     * Support of group names is optional and is indicated by the FeatureMap and NameSupport attribute.
     *
     * @see {@link MatterSpecification.v142.Cluster} § 1.3.7.1.2
     */
    groupName: TlvField(1, TlvString.bound({ maxLength: 16 }))
  });
  Groups2.TlvAddGroupResponse = TlvObject({
    /**
     * This field is set according to the Effect on Receipt section of the AddGroup command.
     *
     * @see {@link MatterSpecification.v142.Cluster} § 1.3.7.7.1
     */
    status: TlvField(0, TlvEnum()),
    /**
     * This field is set to the GroupID field of the received AddGroup command.
     *
     * @see {@link MatterSpecification.v142.Cluster} § 1.3.7.7.2
     */
    groupId: TlvField(1, TlvGroupId)
  });
  Groups2.TlvViewGroupRequest = TlvObject({ groupId: TlvField(0, TlvGroupId) });
  Groups2.TlvViewGroupResponse = TlvObject({
    /**
     * This field is according to the Effect on Receipt section of the ViewGroup command.
     *
     * @see {@link MatterSpecification.v142.Cluster} § 1.3.7.8.1
     */
    status: TlvField(0, TlvEnum()),
    /**
     * This field is set to the GroupID field of the received ViewGroup command.
     *
     * @see {@link MatterSpecification.v142.Cluster} § 1.3.7.8.2
     */
    groupId: TlvField(1, TlvGroupId),
    /**
     * If the status is SUCCESS, and group names are supported, this field is set to the group name associated with
     * that group in the Group Table; otherwise it is set to the empty string.
     *
     * @see {@link MatterSpecification.v142.Cluster} § 1.3.7.8.3
     */
    groupName: TlvField(2, TlvString.bound({ maxLength: 16 }))
  });
  Groups2.TlvGetGroupMembershipRequest = TlvObject({ groupList: TlvField(0, TlvArray(TlvGroupId)) });
  Groups2.TlvGetGroupMembershipResponse = TlvObject({
    /**
     * This field shall contain the remaining capacity of the Group Table of the node. The following values apply:
     *
     *   • 0 - No further groups may be added.
     *
     *   • 0 < Capacity < 0xFE - Capacity holds the number of groups that may be added.
     *
     *   • 0xFE - At least 1 further group may be added (exact number is unknown).
     *
     *   • null - It is unknown if any further groups may be added.
     *
     * @see {@link MatterSpecification.v142.Cluster} § 1.3.7.9.1
     */
    capacity: TlvField(0, TlvNullable(TlvUInt8)),
    /**
     * The GroupList field shall contain either the group IDs of all the groups in the Group Table for which the
     * server endpoint is a member of the group (in the case where the GroupList field of the received
     * GetGroupMembership command was empty), or the group IDs of all the groups in the Group Table for which the
     * server endpoint is a member of the group and for which the group ID was included in the the GroupList field
     * of the received GetGroupMembership command (in the case where the GroupList field of the received
     * GetGroupMembership command was not empty).
     *
     * Zigbee: If the total number of groups will cause the maximum payload length of a frame to be exceeded, then
     * the GroupList field shall contain only as many groups as will fit.
     *
     * @see {@link MatterSpecification.v142.Cluster} § 1.3.7.9.2
     */
    groupList: TlvField(1, TlvArray(TlvGroupId))
  });
  Groups2.TlvRemoveGroupRequest = TlvObject({ groupId: TlvField(0, TlvGroupId) });
  Groups2.TlvRemoveGroupResponse = TlvObject({
    /**
     * This field is according to the Effect on Receipt section of the RemoveGroup command.
     *
     * @see {@link MatterSpecification.v142.Cluster} § 1.3.7.10.1
     */
    status: TlvField(0, TlvEnum()),
    /**
     * This field is set to the GroupID field of the received RemoveGroup command.
     *
     * @see {@link MatterSpecification.v142.Cluster} § 1.3.7.10.2
     */
    groupId: TlvField(1, TlvGroupId)
  });
  Groups2.TlvAddGroupIfIdentifyingRequest = TlvObject({
    /**
     * This field shall be used to identify the group and any associated key material to which the server endpoint
     * is to be added.
     *
     * @see {@link MatterSpecification.v142.Cluster} § 1.3.7.6.1
     */
    groupId: TlvField(0, TlvGroupId),
    /**
     * This field may be set to a human-readable name for the group. If the client has no name for the group, the
     * GroupName field shall be set to the empty string.
     *
     * Support of group names is optional and is indicated by the FeatureMap and NameSupport attribute.
     *
     * @see {@link MatterSpecification.v142.Cluster} § 1.3.7.6.2
     */
    groupName: TlvField(1, TlvString.bound({ maxLength: 16 }))
  });
  Groups2.NameSupport = {
    /**
     * The ability to store a name for a group.
     */
    groupNames: BitFlag(7)
  };
  Groups2.Base = MutableCluster.Component({
    id: 4,
    name: "Groups",
    revision: 4,
    features: {
      /**
       * The Group Names feature indicates the ability to store a name for a group when a group is added.
       *
       * @see {@link MatterSpecification.v142.Cluster} § 1.3.4.1
       */
      groupNames: BitFlag(0)
    },
    attributes: {
      /**
       * This attribute provides legacy, read-only access to whether the Group Names feature is supported. The
       * most significant bit, bit 7 (GroupNames), shall be equal to bit 0 of the FeatureMap attribute (GN
       * Feature). All other bits shall be 0.
       *
       * @see {@link MatterSpecification.v142.Cluster} § 1.3.6.1
       */
      nameSupport: FixedAttribute(0, TlvBitmap(TlvUInt8, Groups2.NameSupportAttribute))
    },
    commands: {
      /**
       * The AddGroup command allows a client to add group membership in a particular group for the server
       * endpoint.
       *
       * @see {@link MatterSpecification.v142.Cluster} § 1.3.7.1
       */
      addGroup: Command(0, Groups2.TlvAddGroupRequest, 0, Groups2.TlvAddGroupResponse, { invokeAcl: AccessLevel.Manage }),
      /**
       * The ViewGroup command allows a client to request that the server responds with a ViewGroupResponse
       * command containing the name string for a particular group.
       *
       * @see {@link MatterSpecification.v142.Cluster} § 1.3.7.2
       */
      viewGroup: Command(1, Groups2.TlvViewGroupRequest, 1, Groups2.TlvViewGroupResponse),
      /**
       * The GetGroupMembership command allows a client to inquire about the group membership of the server
       * endpoint, in a number of ways.
       *
       * @see {@link MatterSpecification.v142.Cluster} § 1.3.7.3
       */
      getGroupMembership: Command(2, Groups2.TlvGetGroupMembershipRequest, 2, Groups2.TlvGetGroupMembershipResponse),
      /**
       * The RemoveGroup command allows a client to request that the server removes the membership for the server
       * endpoint, if any, in a particular group.
       *
       * @see {@link MatterSpecification.v142.Cluster} § 1.3.7.4
       */
      removeGroup: Command(
        3,
        Groups2.TlvRemoveGroupRequest,
        3,
        Groups2.TlvRemoveGroupResponse,
        { invokeAcl: AccessLevel.Manage }
      ),
      /**
       * The RemoveAllGroups command allows a client to direct the server to remove all group associations for the
       * server endpoint.
       *
       * @see {@link MatterSpecification.v142.Cluster} § 1.3.7.5
       */
      removeAllGroups: Command(4, TlvNoArguments, 4, TlvNoResponse, { invokeAcl: AccessLevel.Manage }),
      /**
       * The AddGroupIfIdentifying command allows a client to add group membership in a particular group for the
       * server endpoint, on condition that the endpoint is identifying itself. Identifying functionality is
       * controlled using the Identify cluster, (see Identify Cluster).
       *
       * For correct operation of the AddGroupIfIdentifying command, any endpoint that supports the Groups server
       * cluster shall also support the Identify server cluster.
       *
       * This command might be used to assist configuring group membership in the absence of a commissioning tool.
       *
       * @see {@link MatterSpecification.v142.Cluster} § 1.3.7.6
       */
      addGroupIfIdentifying: Command(
        5,
        Groups2.TlvAddGroupIfIdentifyingRequest,
        5,
        TlvNoResponse,
        { invokeAcl: AccessLevel.Manage }
      )
    },
    /**
     * This metadata controls which GroupsCluster elements matter.js activates for specific feature combinations.
     */
    extensions: MutableCluster.Extensions()
  });
  Groups2.ClusterInstance = MutableCluster({ ...Groups2.Base, supportedFeatures: { groupNames: true } });
  Groups2.Cluster = Groups2.ClusterInstance;
  Groups2.Complete = Groups2.Cluster;
})(Groups || (Groups = {}));
const GroupsCluster = Groups.Cluster;
ClusterRegistry.register(Groups.Complete);
export {
  Groups,
  GroupsCluster
};
//# sourceMappingURL=groups.js.map
