"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 ServerGroupNetworking_exports = {};
__export(ServerGroupNetworking_exports, {
  ServerGroupNetworking: () => ServerGroupNetworking
});
module.exports = __toCommonJS(ServerGroupNetworking_exports);
var import_general = require("@matter/general");
var import_protocol = require("@matter/protocol");
/**
 * @license
 * Copyright 2022-2026 Matter.js Authors
 * SPDX-License-Identifier: Apache-2.0
 */
const logger = import_general.Logger.get("ServerGroupNetworking");
class ServerGroupNetworking {
  #construction;
  #udpInterface;
  #activeGroupMemberships = /* @__PURE__ */ new Map();
  #fabricObservers = /* @__PURE__ */ new Map();
  #observers = new import_general.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 = (0, import_general.Construction)(this);
    this.#construction.start(env);
  }
  async [import_general.Construction.construct](env) {
    const fabrics = env.get(import_protocol.FabricManager);
    for (const fabric of fabrics) {
      if (this.#activeGroupMemberships.has(fabric.fabricIndex)) {
        throw new import_general.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);
    if (!Array.from(memberships.values()).includes(address)) {
      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 = memberships.get(groupId) ?? fabric.groups.multicastAddressFor(groupId);
    memberships.delete(groupId);
    if (!Array.from(memberships.values()).includes(address)) {
      logger.debug(
        `Dropping membership for group ${groupId} on fabric ${fabric.fabricId} (index ${fabricIndex}) with address ${address}`
      );
      await this.#udpInterface.dropMembership(address);
    }
    if (!memberships.size) {
      this.#activeGroupMemberships.delete(fabricIndex);
    }
  }
  #observersForFabric(fabricIndex) {
    let observers = this.#fabricObservers.get(fabricIndex);
    if (observers === void 0) {
      observers = new import_general.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();
  }
}
//# sourceMappingURL=ServerGroupNetworking.js.map
