"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 BindingServer_exports = {};
__export(BindingServer_exports, {
  BindingServer: () => BindingServer
});
module.exports = __toCommonJS(BindingServer_exports);
var import_general = require("@matter/general");
var import_BindingBehavior = require("./BindingBehavior.js");
var import_BindingManager = require("./BindingManager.js");
/**
 * @license
 * Copyright 2022-2026 Matter.js Authors
 * SPDX-License-Identifier: Apache-2.0
 */
class BindingServer extends import_BindingBehavior.BindingBehavior {
  initialize() {
    const manager = this.env.get(import_BindingManager.BindingManager);
    let snapshot = [...this.state.binding];
    for (const entry of snapshot) {
      manager.register(this, this.endpoint, entry);
    }
    this.reactTo(
      this.events.interactionEnd,
      // Must be a regular function, not an arrow, so ReactorBacking.bind() can supply a
      // fresh `this` with a live state reference for each invocation.
      async function() {
        const current = this.state.binding;
        const oldKeys = new Map(snapshot.map((e) => [import_BindingManager.BindingManager.entryKey(e), e]));
        const newKeys = new Map(current.map((e) => [import_BindingManager.BindingManager.entryKey(e), e]));
        let mutated = false;
        for (const [k, e] of newKeys) {
          if (!oldKeys.has(k)) {
            manager.register(this, this.endpoint, e);
            mutated = true;
          }
        }
        const unregistrations = new Array();
        for (const [k, e] of oldKeys) {
          if (!newKeys.has(k)) {
            unregistrations.push(manager.unregister(this, e));
            mutated = true;
          }
        }
        if (unregistrations.length) {
          await Promise.all(unregistrations);
        }
        if (mutated) {
          snapshot = [...current];
        }
      },
      { offline: true }
    );
  }
  async [Symbol.asyncDispose]() {
    await this.env.get(import_BindingManager.BindingManager).disposeServer(this);
    await super[Symbol.asyncDispose]?.();
  }
}
((BindingServer2) => {
  class Events extends import_BindingBehavior.BindingBehavior.Events {
    /**
     * Fires when a binding entry is resolved into a usable peer abstraction — either on
     * startup (for pre-existing entries) or when a controller writes a new entry.
     *
     * The handler receives a {@link BindingResolution} discriminated by `kind`.  The
     * `endpoint` field always carries any declared client cluster behaviors pre-installed —
     * call `endpoint.eventsOf`, `endpoint.stateOf`, or `endpoint.act` just as you would on
     * any other endpoint.
     *
     * See the class-level "Typical developer pattern" example on {@link BindingServer} for the
     * full shape.
     *
     * **`kind: "client"`** — `resolution.node` is the peer {@link ClientNode};
     * `resolution.endpoint` is the materialized remote endpoint.  CASE is already warming
     * when the event fires.  Attribute changes require an explicit subscription (see class doc).
     *
     * **`kind: "group"`** — `resolution.node` is a {@link ClientGroup} keyed by
     * `(fabricIndex, groupId)`; command invocations are sent as group multicast.  Attribute
     * reads and subscriptions are not available for groups.
     *
     * **`kind: "server"`** — `resolution.node` is our own {@link ServerNode};
     * `resolution.endpoint` IS the local target endpoint.  Dispatch stays local, no wire
     * transport involved.  Useful for bridges where one endpoint should react to another.
     */
    established = (0, import_general.AsyncObservable)();
    /**
     * Fires when a previously established binding is removed.  Cleanup mirror of
     * {@link established}: tear down subscriptions, drop cached state, etc.  Fires for every
     * live binding when the endpoint is being disposed.
     *
     * ```ts
     * endpoint.events.binding.removed.on(resolution => {
     *     if (resolution.kind !== "client") return;
     *     // resolution.endpoint is still the same instance that was delivered in established —
     *     // use it to remove subscriptions installed earlier.
     * });
     * ```
     */
    removed = (0, import_general.AsyncObservable)();
  }
  BindingServer2.Events = Events;
})(BindingServer || (BindingServer = {}));
//# sourceMappingURL=BindingServer.js.map
