/**
 * @license
 * Copyright 2022-2026 Matter.js Authors
 * SPDX-License-Identifier: Apache-2.0
 */
import { Construction, InternalError, Logger, ObserverGroup } from "#general";
import { FabricManager } from "#protocol";
const logger = Logger.get("ServerGroupNetworking");
class ServerGroupNetworking {
  #construction;
  #udpInterface;
  #activeGroupMemberships = /* @__PURE__ */ new Map();
  #fabricObservers = /* @__PURE__ */ new Map();
  #observers = new ObserverGroup(this);
  get construction() {
    return this.#construction;
  }
  /**
   * The server group networking is not implemented in the Node.js environment.
   * This class is a placeholder to maintain compatibility with the Matter.js architecture.
   */
  constructor(env, udpInterface) {
    this.#udpInterface = udpInterface;
    this.#construction = Construction(this);
    this.#construction.start(env);
  }
  async [Construction.construct](env) {
    const fabrics = env.get(FabricManager);
    for (const fabric of fabrics) {
      if (this.#activeGroupMemberships.has(fabric.fabricIndex)) {
        throw new InternalError("Group transport interfaces already initialized for this fabric.");
      }
      for (const groupId of fabric.groups.groupKeyIdMap.keys()) {
        await this.#addGroupMembership(groupId, fabric);
      }
      this.#registerFabricGroupObserver(fabric);
    }
    this.#observers.on(fabrics.events.added, async (fabric) => this.#registerFabricGroupObserver(fabric));
    this.#observers.on(fabrics.events.deleting, async (fabric) => {
      const fabricIndex = fabric.fabricIndex;
      this.#observersForFabric(fabricIndex).close();
      this.#fabricObservers.delete(fabricIndex);
      const memberships = this.#activeGroupMemberships.get(fabricIndex);
      if (memberships === void 0 || memberships.size === 0) {
        this.#activeGroupMemberships.delete(fabricIndex);
        return;
      }
      for (const groupId of memberships.keys()) {
        await this.#dropGroupMembership(groupId, fabric);
      }
      this.#activeGroupMemberships.delete(fabricIndex);
    });
    this.#observers.on(fabrics.events.replaced, async (fabric) => {
      const fabricIndex = fabric.fabricIndex;
      this.#observersForFabric(fabricIndex).close();
      this.#fabricObservers.delete(fabricIndex);
      this.#registerFabricGroupObserver(fabric);
      const { groupKeyIdMap } = fabric.groups;
      for (const groupId of groupKeyIdMap.keys()) {
        await this.#addGroupMembership(groupId, fabric);
      }
      const memberships = this.#activeGroupMemberships.get(fabricIndex) ?? /* @__PURE__ */ new Map();
      if (memberships.size !== 0) {
        for (const groupId of memberships.keys()) {
          if (!groupKeyIdMap.has(groupId)) {
            await this.#dropGroupMembership(groupId, fabric);
          }
        }
      }
    });
  }
  async #addGroupMembership(groupId, fabric) {
    const fabricIndex = fabric.fabricIndex;
    const memberships = this.#activeGroupMemberships.get(fabricIndex) ?? /* @__PURE__ */ new Map();
    if (memberships.has(groupId)) {
      return;
    }
    const address = fabric.groups.multicastAddressFor(groupId);
    logger.debug(
      `Adding membership for group ${groupId} on fabric ${fabric.fabricId} (index ${fabricIndex}) with address ${address}`
    );
    await this.#udpInterface.addMembership(address);
    memberships.set(groupId, address);
    this.#activeGroupMemberships.set(fabricIndex, memberships);
  }
  async #dropGroupMembership(groupId, fabric) {
    const fabricIndex = fabric.fabricIndex;
    const memberships = this.#activeGroupMemberships.get(fabricIndex);
    if (memberships === void 0 || memberships.size === 0) {
      return;
    }
    const address = fabric.groups.multicastAddressFor(groupId);
    logger.debug(
      `Dropping membership for group ${groupId} on fabric ${fabric.fabricId} (index ${fabricIndex}) with address ${address}`
    );
    await this.#udpInterface.dropMembership(address);
    memberships.delete(groupId);
    if (!memberships.size) {
      this.#activeGroupMemberships.delete(fabricIndex);
    }
  }
  #observersForFabric(fabricIndex) {
    let observers = this.#fabricObservers.get(fabricIndex);
    if (observers === void 0) {
      observers = new ObserverGroup(this);
      this.#fabricObservers.set(fabricIndex, observers);
    }
    return observers;
  }
  #registerFabricGroupObserver(fabric) {
    const fabricIndex = fabric.fabricIndex;
    const observers = this.#observersForFabric(fabricIndex);
    observers.on(
      fabric.groups.groupKeyIdMap.added,
      async (groupId) => await this.#addGroupMembership(groupId, fabric)
    );
    observers.on(fabric.groups.groupKeyIdMap.deleted, async (groupId) => this.#dropGroupMembership(groupId, fabric));
  }
  close() {
    this.#construction.close();
    this.#observers.close();
    this.#fabricObservers.forEach((observer) => observer.close());
    this.#activeGroupMemberships.clear();
    this.#fabricObservers.clear();
  }
}
export {
  ServerGroupNetworking
};
//# sourceMappingURL=ServerGroupNetworking.js.map
