"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var GroupsServer_exports = {};
__export(GroupsServer_exports, {
  GroupsServer: () => GroupsServer
});
module.exports = __toCommonJS(GroupsServer_exports);
var import_group_key_management = require("#behaviors/group-key-management");
var import_identify = require("#behaviors/identify");
var import_scenes_management = require("#behaviors/scenes-management");
var import_root = require("#endpoints/root");
var import_general = require("@matter/general");
var import_protocol = require("@matter/protocol");
var import_types = require("@matter/types");
var import_groups = require("@matter/types/clusters/groups");
var import_GroupsBehavior = require("./GroupsBehavior.js");
/**
 * @license
 * Copyright 2022-2026 Matter.js Authors
 * SPDX-License-Identifier: Apache-2.0
 */
const logger = import_general.Logger.get("GroupsServer");
const { commands } = import_groups.Groups.schema;
const addGroup = commands.require("AddGroup");
const addGroupIfIdentifying = commands.require("AddGroupIfIdentifying");
const addGroupResponse = commands.require("AddGroupResponse");
const viewGroupResponse = commands.require("ViewGroupResponse");
const removeGroupResponse = commands.require("RemoveGroupResponse");
const GroupsSchema = import_groups.Groups.schema.extend(
  void 0,
  addGroup.extend(
    void 0,
    addGroup.fields.extend("GroupId", { constraint: "none" }),
    addGroup.fields.extend("GroupName", { constraint: "none" })
  ),
  addGroupIfIdentifying.extend(
    void 0,
    addGroupIfIdentifying.fields.extend("GroupId", { constraint: "none" }),
    addGroupIfIdentifying.fields.extend("GroupName", { constraint: "none" })
  ),
  addGroupResponse.extend(void 0, addGroupResponse.fields.extend("GroupId", { constraint: "none" })),
  viewGroupResponse.extend(
    void 0,
    viewGroupResponse.fields.extend("GroupId", { constraint: "none" }),
    viewGroupResponse.fields.extend("GroupName", { constraint: "none" })
  ),
  removeGroupResponse.extend(void 0, removeGroupResponse.fields.extend("GroupId", { constraint: "none" }))
);
const GroupsBase = import_GroupsBehavior.GroupsBehavior.for(import_groups.Groups, GroupsSchema).with(import_groups.Groups.Feature.GroupNames);
class GroupsServer extends GroupsBase {
  initialize() {
    this.state.nameSupport.groupNames = this.features.groupNames;
  }
  // We need to search the root here ourselves because we cannot include ServerNode because else we generate a
  // circular dependency
  get #rootEndpoint() {
    const rootEndpoint = this.endpoint.ownerOfType(import_root.RootEndpoint);
    if (rootEndpoint === void 0) {
      throw new import_general.InternalError("RootEndpoint not found");
    }
    return rootEndpoint;
  }
  async #actOnGroupKeyManagement(act) {
    (0, import_protocol.assertRemoteActor)(this.context);
    const agent = this.#rootEndpoint.agentFor(this.context);
    const gkm = agent.get(import_group_key_management.GroupKeyManagementServer);
    await agent.context.transaction.addResources(gkm);
    await agent.context.transaction.begin();
    return act(this.context.session.associatedFabric, gkm);
  }
  async addGroup({ groupId, groupName }) {
    (0, import_protocol.assertRemoteActor)(this.context);
    const fabric = this.context.session.associatedFabric;
    if (groupId < 1) {
      return { status: import_types.Status.ConstraintError, groupId };
    }
    if (groupName.length > 16) {
      return { status: import_types.Status.ConstraintError, groupId };
    }
    if (!fabric.groups.groupKeyIdMap.has(groupId)) {
      return { status: import_types.Status.UnsupportedAccess, groupId };
    }
    const endpointNumber = this.endpoint.number;
    try {
      await this.#actOnGroupKeyManagement(
        (fabric2, gkm) => gkm.addEndpointForGroup(fabric2, groupId, endpointNumber, groupName)
      );
    } catch (error) {
      logger.debug("Could not add group", error);
      import_types.StatusResponseError.accept(error);
      return { status: error.code, groupId };
    }
    return { status: import_types.Status.Success, groupId };
  }
  viewGroup({ groupId }) {
    (0, import_protocol.assertRemoteActor)(this.context);
    const fabric = this.context.session.associatedFabric;
    if (groupId < 1) {
      return { status: import_types.Status.ConstraintError, groupId, groupName: "" };
    }
    const fabricIndex = fabric.fabricIndex;
    const endpointNumber = this.endpoint.number;
    const { groupTable } = this.#rootEndpoint.stateOf(import_group_key_management.GroupKeyManagementServer);
    const groupEntry = groupTable.find((entry) => entry.groupId === groupId && entry.fabricIndex === fabricIndex);
    if (groupEntry === void 0 || !groupEntry.endpoints.includes(endpointNumber)) {
      return { status: import_types.Status.NotFound, groupId, groupName: "" };
    }
    return { status: import_types.Status.Success, groupId, groupName: groupEntry.groupName ?? "" };
  }
  async getGroupMembership({
    groupList
  }) {
    (0, import_protocol.assertRemoteActor)(this.context);
    const fabric = this.context.session.associatedFabric;
    const fabricIndex = fabric.fabricIndex;
    const endpointNumber = this.endpoint.number;
    const { groupTable } = this.#rootEndpoint.stateOf(import_group_key_management.GroupKeyManagementServer);
    const endpointGroups = groupTable.filter(
      (entry) => entry.endpoints.includes(endpointNumber) && entry.fabricIndex === fabricIndex
    );
    const fabricGroupsList = endpointGroups.map((entry) => entry.groupId);
    if (groupList.length === 0) {
      return { capacity: 254 - fabricGroupsList.length, groupList: fabricGroupsList };
    }
    const filteredGroupsList = groupList.filter((groupId) => fabricGroupsList.includes(groupId));
    return { capacity: 254 - fabricGroupsList.length, groupList: filteredGroupsList };
  }
  async removeGroup({ groupId }) {
    if (groupId < 1) {
      return { status: import_types.Status.ConstraintError, groupId };
    }
    try {
      (0, import_protocol.assertRemoteActor)(this.context);
      if (await this.#actOnGroupKeyManagement(
        (fabric, gkm) => gkm.removeEndpoint(fabric, this.endpoint.number, groupId)
      )) {
        if (this.agent.has(import_scenes_management.ScenesManagementServer)) {
          this.agent.get(import_scenes_management.ScenesManagementServer).removeScenesForGroupOnFabric(this.context.session.associatedFabric.fabricIndex, groupId);
        }
        return { status: import_types.Status.Success, groupId };
      }
      return { status: import_types.Status.NotFound, groupId };
    } catch (error) {
      import_types.StatusResponseError.accept(error);
      return { status: error.code, groupId };
    }
  }
  async removeAllGroups() {
    try {
      (0, import_protocol.assertRemoteActor)(this.context);
      await this.#actOnGroupKeyManagement((fabric, gkm) => gkm.removeEndpoint(fabric, this.endpoint.number));
      if (this.agent.has(import_scenes_management.ScenesManagementServer)) {
        this.agent.get(import_scenes_management.ScenesManagementServer).removeScenesForAllGroupsForFabric(this.context.session.associatedFabric.fabricIndex);
      }
    } catch (error) {
      import_types.StatusResponseError.accept(error);
      throw error;
    }
  }
  async addGroupIfIdentifying({ groupId, groupName }) {
    if (this.endpoint.stateOf(import_identify.IdentifyBehavior).identifyTime > 0) {
      const { status } = await this.addGroup({ groupId, groupName });
      if (status !== import_types.Status.Success) {
        throw new import_types.StatusResponseError(`Failed to add group ${groupId}`, status);
      }
    }
  }
}
//# sourceMappingURL=GroupsServer.js.map
