"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 WebRtcTransportRequestorServer_exports = {};
__export(WebRtcTransportRequestorServer_exports, {
  WebRtcTransportRequestorServer: () => WebRtcTransportRequestorServer
});
module.exports = __toCommonJS(WebRtcTransportRequestorServer_exports);
var import_access_control = require("#behaviors/access-control");
var import_Node = require("#node/Node.js");
var import_general = require("@matter/general");
var import_protocol = require("@matter/protocol");
var import_types = require("@matter/types");
var import_access_control2 = require("@matter/types/clusters/access-control");
var import_web_rtc_transport_requestor = require("@matter/types/clusters/web-rtc-transport-requestor");
var import_WebRtcTransportRequestorBehavior = require("./WebRtcTransportRequestorBehavior.js");
/**
 * @license
 * Copyright 2022-2026 Matter.js Authors
 * SPDX-License-Identifier: Apache-2.0
 */
const logger = import_general.Logger.get("WebRtcTransportRequestorServer");
class WebRtcTransportRequestorServer extends import_WebRtcTransportRequestorBehavior.WebRtcTransportRequestorBehavior {
  async initialize() {
    const node = import_Node.Node.forEndpoint(this.endpoint);
    logger.info(
      `WebRtcTransportRequestor initialized on endpoint=${this.endpoint.number} (id="${this.endpoint.id}")`
    );
    this.reactTo(node.lifecycle.online, this.#nodeOnline);
    if (node.lifecycle.isOnline) {
      await this.#nodeOnline();
    }
  }
  async #nodeOnline() {
    const fabricAuthority = this.env.get(import_protocol.FabricAuthority);
    const ownFabric = fabricAuthority.fabrics[0];
    if (!ownFabric) {
      this.reactTo(fabricAuthority.fabricAdded, this.#nodeOnline, { once: true });
      return;
    }
    const node = import_Node.Node.forEndpoint(this.endpoint);
    await node.act((agent) => agent.load(import_access_control.AccessControlServer));
    if (node.behaviors.has(import_access_control.AccessControlServer)) {
      if (!node.stateOf(import_access_control.AccessControlServer).acl.some(
        ({ fabricIndex, privilege, authMode, subjects, targets }) => fabricIndex === ownFabric.fabricIndex && privilege === import_access_control2.AccessControl.AccessControlEntryPrivilege.Operate && authMode === import_access_control2.AccessControl.AccessControlEntryAuthMode.Case && subjects?.length === 0 && targets?.length === 1 && targets[0].endpoint === this.endpoint.number && targets[0].cluster === import_web_rtc_transport_requestor.WebRtcTransportRequestor.id
      )) {
        const acl = [
          ...node.stateOf(import_access_control.AccessControlServer).acl,
          {
            fabricIndex: ownFabric.fabricIndex,
            privilege: import_access_control2.AccessControl.AccessControlEntryPrivilege.Operate,
            authMode: import_access_control2.AccessControl.AccessControlEntryAuthMode.Case,
            subjects: [],
            targets: [{ endpoint: this.endpoint.number, cluster: import_web_rtc_transport_requestor.WebRtcTransportRequestor.id }]
          }
        ];
        await node.setStateOf(import_access_control.AccessControlServer, { acl });
      }
    }
  }
  /**
   * Register or update a WebRTC session you have initiated with a peer. A session must be registered before the peer's
   * signaling commands for the matching session id are accepted, and registration populates the `currentSessions`
   * attribute. Re-registering an existing id replaces the entry.
   */
  upsertSession(session) {
    const enriched = {
      ...session,
      videoStreamId: session.videoStreams?.[0] ?? null,
      audioStreamId: session.audioStreams?.[0] ?? null
    };
    const sessions = this.state.currentSessions;
    const idx = sessions.findIndex((s) => s.id === session.id);
    if (idx === -1) {
      this.state.currentSessions = [...sessions, enriched];
    } else {
      this.state.currentSessions = sessions.map((s, i) => i === idx ? enriched : s);
    }
  }
  /** Stop tracking a session, e.g. after you tear down the stream locally. No-op if the id is unknown. */
  removeSession(id) {
    const sessions = this.state.currentSessions;
    if (sessions.some((s) => s.id === id)) {
      this.state.currentSessions = sessions.filter((s) => s.id !== id);
    }
  }
  /**
   * Invoked by the peer to deliver an SDP offer. Surfaces it via the {@link WebRtcTransportRequestorServer.Events}
   * `offer` event.
   */
  async offer(request) {
    logger.debug(`incoming Offer webRtcSessionId=${request.webRtcSessionId} sdpLen=${request.sdp.length}`);
    const session = this.#findSessionStrict(request.webRtcSessionId);
    this.events.offer.emit(session, request);
  }
  /**
   * Invoked by the peer to deliver an SDP answer. Surfaces it via the {@link WebRtcTransportRequestorServer.Events}
   * `answer` event.
   */
  async answer(request) {
    logger.debug(`incoming Answer webRtcSessionId=${request.webRtcSessionId} sdpLen=${request.sdp.length}`);
    const session = this.#findSessionStrict(request.webRtcSessionId);
    this.events.answer.emit(session, request.sdp);
  }
  /** Invoked by the peer to deliver ICE candidates. Surfaces them via the {@link WebRtcTransportRequestorServer.Events}
   *  `iceCandidates` event.
   */
  async iceCandidates(request) {
    logger.debug(
      `incoming ICECandidates webRtcSessionId=${request.webRtcSessionId} count=${request.iceCandidates.length}`
    );
    if (request.iceCandidates.length === 0) {
      throw new import_types.StatusResponseError("ICE candidates list must not be empty", import_types.Status.InvalidCommand);
    }
    const session = this.#findSessionStrict(request.webRtcSessionId);
    this.events.iceCandidates.emit(session, request.iceCandidates);
  }
  /** Invoked by the peer to end a session. Removes it from tracking and surfaces it via the
   * {@link WebRtcTransportRequestorServer.Events} `end` event.
   */
  async end(request) {
    logger.debug(`incoming End webRtcSessionId=${request.webRtcSessionId} reason=${request.reason}`);
    const session = this.#findSessionStrict(request.webRtcSessionId);
    this.removeSession(request.webRtcSessionId);
    this.events.end.emit(session, request.reason);
  }
  #findSessionStrict(id) {
    (0, import_protocol.assertRemoteActor)(this.context);
    import_protocol.NodeSession.assert(this.context.session);
    const peer = this.context.session.peerAddress;
    const session = this.state.currentSessions.find((s) => s.id === id);
    if (session === void 0 || session.fabricIndex !== peer.fabricIndex || session.peerNodeId !== peer.nodeId) {
      throw new import_types.StatusResponseError(`WebRTC session ${id} not found`, import_types.Status.NotFound);
    }
    return session;
  }
}
((WebRtcTransportRequestorServer2) => {
  class Events extends import_WebRtcTransportRequestorBehavior.WebRtcTransportRequestorBehavior.Events {
    /** Peer sent an SDP offer for a tracked session; apply it to your peer connection. */
    offer = (0, import_general.Observable)();
    /** Peer sent an SDP answer for a tracked session. */
    answer = (0, import_general.Observable)();
    /** Peer sent ICE candidates for a tracked session; add them to your peer connection. */
    iceCandidates = (0, import_general.Observable)();
    /** Peer ended a session; the session is already removed from tracking when this fires. */
    end = (0, import_general.Observable)();
  }
  WebRtcTransportRequestorServer2.Events = Events;
})(WebRtcTransportRequestorServer || (WebRtcTransportRequestorServer = {}));
//# sourceMappingURL=WebRtcTransportRequestorServer.js.map
