"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __knownSymbol = (name, symbol) => (symbol = Symbol[name]) ? symbol : Symbol.for("Symbol." + name);
var __typeError = (msg) => {
  throw TypeError(msg);
};
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 __using = (stack, value, async) => {
  if (value != null) {
    if (typeof value !== "object" && typeof value !== "function") __typeError("Object expected");
    var dispose, inner;
    if (async) dispose = value[__knownSymbol("asyncDispose")];
    if (dispose === void 0) {
      dispose = value[__knownSymbol("dispose")];
      if (async) inner = dispose;
    }
    if (typeof dispose !== "function") __typeError("Object not disposable");
    if (inner) dispose = function() {
      try {
        inner.call(this);
      } catch (e) {
        return Promise.reject(e);
      }
    };
    stack.push([async, dispose, value]);
  } else if (async) {
    stack.push([async]);
  }
  return value;
};
var __callDispose = (stack, error, hasError) => {
  var E = typeof SuppressedError === "function" ? SuppressedError : function(e, s, m, _) {
    return _ = Error(m), _.name = "SuppressedError", _.error = e, _.suppressed = s, _;
  };
  var fail = (e) => error = hasError ? new E(e, error, "An error was suppressed during disposal") : (hasError = true, e);
  var next = (it) => {
    while (it = stack.pop()) {
      try {
        var result = it[1] && it[1].call(it[2]);
        if (it[0]) return Promise.resolve(result).then(next, (e) => (fail(e), next()));
      } catch (e) {
        fail(e);
      }
    }
    if (hasError) throw error;
  };
  return next();
};
var InteractionServer_exports = {};
__export(InteractionServer_exports, {
  InteractionServer: () => InteractionServer
});
module.exports = __toCommonJS(InteractionServer_exports);
var import_NodeActivity = require("#behavior/context/NodeActivity.js");
var import_access_control = require("#behaviors/access-control");
var import_general = require("#general");
var import_model = require("#model");
var import_protocol = require("#protocol");
var import_types = require("#types");
var import_OnlineServerInteraction = require("./OnlineServerInteraction.js");
var import_ServerSubscription = require("./ServerSubscription.js");
/**
 * @license
 * Copyright 2022-2025 Matter.js Authors
 * SPDX-License-Identifier: Apache-2.0
 */
const logger = import_general.Logger.get("InteractionServer");
function validateReadAttributesPath(path, isGroupSession = false) {
  if (isGroupSession) {
    throw new import_types.StatusResponseError("Illegal read request with group session", import_types.StatusCode.InvalidAction);
  }
  const { clusterId, attributeId } = path;
  if (clusterId === void 0 && attributeId !== void 0) {
    if (!import_model.GLOBAL_IDS.has(attributeId)) {
      throw new import_types.StatusResponseError(
        `Illegal read request for wildcard cluster and non global attribute ${attributeId}`,
        import_types.StatusCode.InvalidAction
      );
    }
  }
}
function validateReadEventPath(path, isGroupSession = false) {
  const { clusterId, eventId } = path;
  if (clusterId === void 0 && eventId !== void 0) {
    throw new import_types.StatusResponseError("Illegal read request with wildcard cluster ID", import_types.StatusCode.InvalidAction);
  }
  if (isGroupSession) {
    throw new import_types.StatusResponseError("Illegal read request with group session", import_types.StatusCode.InvalidAction);
  }
}
function clusterPathToId({ nodeId, endpointId, clusterId }) {
  return `${nodeId}/${endpointId}/${clusterId}`;
}
class InteractionServer {
  id = import_types.INTERACTION_PROTOCOL_ID;
  requiresSecureSession = true;
  #context;
  #nextSubscriptionId;
  #isClosing = false;
  #clientHandler;
  #subscriptionConfig;
  #maxPathsPerInvoke;
  #subscriptionEstablishmentStarted = (0, import_general.Observable)();
  #node;
  #activity;
  #newActivityBlocked = false;
  #aclServer;
  #serverInteraction;
  constructor(node, sessions) {
    this.#nextSubscriptionId = node.env.get(import_general.Crypto).randomUint32;
    this.#context = {
      sessions,
      exchangeManager: node.env.get(import_protocol.ExchangeManager)
    };
    this.#subscriptionConfig = import_ServerSubscription.ServerSubscriptionConfig.of(node.state.network.subscriptionOptions);
    this.#maxPathsPerInvoke = node.state.basicInformation.maxPathsPerInvoke ?? import_types.DEFAULT_MAX_PATHS_PER_INVOKE;
    this.#activity = node.env.get(import_NodeActivity.NodeActivity);
    this.#node = node;
    this.#serverInteraction = new import_OnlineServerInteraction.OnlineServerInteraction(node.protocol);
  }
  async [Symbol.asyncDispose]() {
    await this.close();
  }
  blockNewActivity() {
    this.#newActivityBlocked = true;
  }
  get isClosing() {
    return this.#isClosing;
  }
  get maxPathsPerInvoke() {
    return this.#maxPathsPerInvoke;
  }
  get subscriptionEstablishmentStarted() {
    return this.#subscriptionEstablishmentStarted;
  }
  async onNewExchange(exchange, message) {
    var _stack = [];
    try {
      if (this.#newActivityBlocked || this.isClosing) {
        return;
      }
      if (message.payloadHeader.messageType === import_protocol.MessageType.ReportData && this.clientHandler) {
        return this.clientHandler.onNewExchange(exchange, message);
      }
      const activity = __using(_stack, this.#activity.begin(`session#${exchange.session.id.toString(16)}`));
      exchange[import_NodeActivity.NodeActivity.activityKey] = activity;
      return new import_protocol.InteractionServerMessenger(exchange).handleRequest(this).finally(() => delete exchange[import_NodeActivity.NodeActivity.activityKey]);
    } catch (_) {
      var _error = _, _hasError = true;
    } finally {
      __callDispose(_stack, _error, _hasError);
    }
  }
  get aclServer() {
    if (this.#aclServer !== void 0) {
      return this.#aclServer;
    }
    const aclServer = this.#node.act((agent) => agent.get(import_access_control.AccessControlServer));
    if (import_general.MaybePromise.is(aclServer)) {
      throw new import_general.InternalError("AccessControlServer should already be initialized.");
    }
    return this.#aclServer = aclServer;
  }
  get clientHandler() {
    return this.#clientHandler;
  }
  set clientHandler(clientHandler) {
    this.#clientHandler = clientHandler;
  }
  #prepareOnlineContext(exchange, message, fabricFiltered, timed = false) {
    return {
      activity: exchange[import_NodeActivity.NodeActivity.activityKey],
      fabricFiltered,
      timed,
      message,
      exchange,
      node: this.#node
    };
  }
  /**
   * Returns an iterator that yields the data reports and events data for the given read request.
   */
  async *#executeReadInteraction(readRequest, exchange, message) {
    const readContext = this.#prepareOnlineContext(exchange, message, readRequest.isFabricFiltered);
    for await (const chunk of this.#serverInteraction.read(readRequest, readContext)) {
      for (const report of chunk) {
        yield import_protocol.InteractionServerMessenger.convertServerInteractionReport(report);
      }
    }
  }
  async handleReadRequest(exchange, readRequest, message) {
    const {
      attributeRequests,
      eventRequests,
      isFabricFiltered,
      dataVersionFilters,
      eventFilters,
      interactionModelRevision
    } = readRequest;
    logger.debug(() => [
      "Read \xAB",
      exchange.via,
      import_general.Diagnostic.asFlags({ fabricFiltered: isFabricFiltered }),
      import_general.Diagnostic.dict({
        attributes: `${attributeRequests?.map((path) => this.#node.protocol.inspectPath(path)).join(", ") ?? "none"}${dataVersionFilters?.length ? ` with ${dataVersionFilters?.length} filters` : ""}`,
        events: `${eventRequests?.map((path) => this.#node.protocol.inspectPath(path)).join(", ") ?? "none"}${eventFilters?.length ? `, ${eventFilters?.length} filters` : ""}`
      })
    ]);
    if (interactionModelRevision > import_model.Specification.INTERACTION_MODEL_REVISION) {
      logger.debug(
        `Interaction model revision of sender ${interactionModelRevision} is higher than supported ${import_model.Specification.INTERACTION_MODEL_REVISION}.`
      );
    }
    if (attributeRequests === void 0 && eventRequests === void 0) {
      return {
        dataReport: {
          interactionModelRevision: import_model.Specification.INTERACTION_MODEL_REVISION,
          suppressResponse: true
        }
      };
    }
    if (message.packetHeader.sessionType !== import_protocol.SessionType.Unicast) {
      throw new import_types.StatusResponseError(
        "Reads are only allowed on unicast sessions",
        // Means "No groups"
        import_types.StatusCode.InvalidAction
      );
    }
    return {
      dataReport: {
        interactionModelRevision: import_model.Specification.INTERACTION_MODEL_REVISION,
        suppressResponse: true
      },
      payload: this.#executeReadInteraction(readRequest, exchange, message)
    };
  }
  async handleWriteRequest(exchange, writeRequest, message) {
    const { suppressResponse, timedRequest, writeRequests, interactionModelRevision, moreChunkedMessages } = writeRequest;
    const sessionType = message.packetHeader.sessionType;
    logger.info(() => [
      "Write \xAB",
      exchange.via,
      import_general.Diagnostic.asFlags({ suppressResponse, moreChunkedMessages }),
      import_general.Diagnostic.weak(writeRequests.map((req) => this.#node.protocol.inspectPath(req.path)).join(", "))
    ]);
    if (moreChunkedMessages && suppressResponse) {
      throw new import_types.StatusResponseError(
        "MoreChunkedMessages and SuppressResponse cannot be used together in write messages",
        import_types.StatusCode.InvalidAction
      );
    }
    if (interactionModelRevision > import_model.Specification.INTERACTION_MODEL_REVISION) {
      logger.debug(
        `Interaction model revision of sender ${interactionModelRevision} is higher than supported ${import_model.Specification.INTERACTION_MODEL_REVISION}.`
      );
    }
    const receivedWithinTimedInteraction = exchange.hasActiveTimedInteraction();
    if (receivedWithinTimedInteraction && moreChunkedMessages) {
      throw new import_types.StatusResponseError(
        "Write Request action that is part of a Timed Write Interaction SHALL NOT be chunked.",
        import_types.StatusCode.InvalidAction
      );
    }
    if (exchange.hasExpiredTimedInteraction()) {
      exchange.clearTimedInteraction();
      throw new import_types.StatusResponseError(`Timed request window expired. Decline write request.`, import_types.StatusCode.Timeout);
    }
    if (timedRequest !== exchange.hasTimedInteraction()) {
      throw new import_types.StatusResponseError(
        `timedRequest flag of write interaction (${timedRequest}) mismatch with expected timed interaction (${receivedWithinTimedInteraction}).`,
        import_types.StatusCode.TimedRequestMismatch
      );
    }
    if (receivedWithinTimedInteraction) {
      logger.debug("Write request for timed interaction on", exchange.channel.name);
      exchange.clearTimedInteraction();
      if (sessionType !== import_protocol.SessionType.Unicast) {
        throw new import_types.StatusResponseError(
          "Write requests are only allowed on unicast sessions when a timed interaction is running.",
          import_types.StatusCode.InvalidAction
        );
      }
    }
    if (sessionType === import_protocol.SessionType.Group && !suppressResponse) {
      throw new import_types.StatusResponseError(
        "Write requests are only allowed as group casts when suppressResponse=true.",
        import_types.StatusCode.InvalidAction
      );
    }
    const result = await this.#serverInteraction.write(
      writeRequest,
      this.#prepareOnlineContext(
        exchange,
        message,
        true,
        // always fabric filtered
        receivedWithinTimedInteraction
      )
    );
    return {
      writeResponses: result?.map(({ path, status, clusterStatus }) => ({
        path,
        status: { status, clusterStatus }
      })),
      interactionModelRevision: import_model.Specification.INTERACTION_MODEL_REVISION
    };
  }
  async handleSubscribeRequest(exchange, request, messenger, message) {
    const {
      minIntervalFloorSeconds,
      maxIntervalCeilingSeconds,
      attributeRequests,
      dataVersionFilters,
      eventRequests,
      eventFilters,
      keepSubscriptions,
      isFabricFiltered,
      interactionModelRevision
    } = request;
    logger.info(() => [
      "Subscribe \xAB",
      exchange.via,
      import_general.Diagnostic.asFlags({ fabricFiltered: isFabricFiltered, keepSubscriptions }),
      import_general.Diagnostic.dict({
        attributePaths: attributeRequests?.length,
        eventPaths: eventRequests?.length
      })
    ]);
    if (interactionModelRevision > import_model.Specification.INTERACTION_MODEL_REVISION) {
      logger.debug(
        `Interaction model revision of sender ${interactionModelRevision} is higher than supported ${import_model.Specification.INTERACTION_MODEL_REVISION}.`
      );
    }
    if (message.packetHeader.sessionType !== import_protocol.SessionType.Unicast) {
      throw new import_types.StatusResponseError(
        "Subscriptions are only allowed on unicast sessions",
        import_types.StatusCode.InvalidAction
      );
    }
    import_protocol.NodeSession.assert(exchange.session, "Subscriptions are only implemented on secure sessions");
    const session = exchange.session;
    const fabric = session.fabric;
    if (fabric !== void 0 && !keepSubscriptions) {
      const clearedCount = await this.#context.sessions.clearSubscriptionsForNode(
        fabric.addressOf(session.peerNodeId),
        true
      );
      if (clearedCount > 0) {
        logger.debug(
          `Cleared ${clearedCount} subscriptions for Subscriber node ${session.peerNodeId} because keepSubscriptions=false`
        );
      }
    }
    if ((!Array.isArray(attributeRequests) || attributeRequests.length === 0) && (!Array.isArray(eventRequests) || eventRequests.length === 0)) {
      throw new import_types.StatusResponseError("No attributes or events requested", import_types.StatusCode.InvalidAction);
    }
    logger.debug(() => [
      "Subscribe request details \xAB",
      exchange.via,
      import_general.Diagnostic.dict({
        attributes: attributeRequests?.length ? attributeRequests?.map((path) => this.#node.protocol.inspectPath(path)).join(", ") : void 0,
        dataVersionFilters: dataVersionFilters?.length ? dataVersionFilters.map(
          ({ path: { nodeId, endpointId, clusterId }, dataVersion }) => `${clusterPathToId({ nodeId, endpointId, clusterId })}=${dataVersion}`
        ).join(", ") : void 0,
        events: eventRequests?.length ? eventRequests.map((path) => this.#node.protocol.inspectPath(path)).join(", ") : void 0,
        eventFilters: eventFilters?.length ? eventFilters.map((filter) => `${filter.nodeId}/${filter.eventMin}`).join(", ") : void 0
      })
    ]);
    attributeRequests?.forEach((path) => validateReadAttributesPath(path));
    eventRequests?.forEach((path) => validateReadEventPath(path));
    if (minIntervalFloorSeconds < 0) {
      throw new import_types.StatusResponseError(
        "minIntervalFloorSeconds should be greater or equal to 0",
        import_types.StatusCode.InvalidAction
      );
    }
    if (maxIntervalCeilingSeconds < 0) {
      throw new import_types.StatusResponseError(
        "maxIntervalCeilingSeconds should be greater or equal to 0",
        import_types.StatusCode.InvalidAction
      );
    }
    if (maxIntervalCeilingSeconds < minIntervalFloorSeconds) {
      throw new import_types.StatusResponseError(
        "maxIntervalCeilingSeconds should be greater or equal to minIntervalFloorSeconds",
        import_types.StatusCode.InvalidAction
      );
    }
    if (this.#nextSubscriptionId === 4294967295) this.#nextSubscriptionId = 0;
    const subscriptionId = this.#nextSubscriptionId++;
    this.#subscriptionEstablishmentStarted.emit(session.peerAddress);
    let subscription;
    try {
      subscription = await this.#establishSubscription(
        subscriptionId,
        request,
        messenger,
        session,
        exchange,
        message
      );
    } catch (error) {
      logger.error(
        `Subscription ${subscriptionId} for Session ${session.id}: Error while sending initial data reports:`,
        error instanceof import_general.MatterError ? error.message : error
      );
      if (error instanceof import_types.StatusResponseError && !(error instanceof import_types.ReceivedStatusResponseError)) {
        logger.info(
          "Status",
          import_general.Diagnostic.strong(`${import_types.Status[error.code]}(${error.code})`),
          "\xBB",
          exchange.via,
          "Error:",
          import_general.Diagnostic.errorMessage(error)
        );
        await messenger.sendStatus(error.code, {
          logContext: {
            for: "I/SubscriptionSeed-Status"
          }
        });
      }
      await messenger.close();
      return;
    }
    const maxInterval = subscription.maxInterval;
    await messenger.send(
      import_protocol.MessageType.SubscribeResponse,
      import_types.TlvSubscribeResponse.encode({
        subscriptionId,
        maxInterval: import_general.Seconds.of(maxInterval),
        interactionModelRevision: import_model.Specification.INTERACTION_MODEL_REVISION
      }),
      {
        logContext: {
          subId: subscriptionId,
          maxInterval
        }
      }
    );
    subscription.activate();
  }
  async #establishSubscription(id, {
    minIntervalFloorSeconds,
    maxIntervalCeilingSeconds,
    attributeRequests,
    dataVersionFilters,
    eventRequests,
    eventFilters,
    isFabricFiltered
  }, messenger, session, exchange, message) {
    const context = {
      session,
      node: this.#node,
      initiateExchange: (address, protocolId) => this.#context.exchangeManager.initiateExchange(address, protocolId)
    };
    const subscription = new import_ServerSubscription.ServerSubscription({
      id,
      context,
      criteria: {
        attributeRequests,
        dataVersionFilters,
        eventRequests,
        eventFilters,
        isFabricFiltered
      },
      minIntervalFloor: (0, import_general.Seconds)(minIntervalFloorSeconds),
      maxIntervalCeiling: (0, import_general.Seconds)(maxIntervalCeilingSeconds),
      subscriptionOptions: this.#subscriptionConfig
    });
    const readContext = this.#prepareOnlineContext(exchange, message, isFabricFiltered);
    try {
      await subscription.sendInitialReport(messenger, readContext);
    } catch (error) {
      await subscription.close();
      throw error;
    }
    logger.info(
      "Subscribe successful \xBB",
      exchange.via,
      import_general.Diagnostic.dict({
        subId: id,
        timing: `${import_general.Duration.format((0, import_general.Seconds)(minIntervalFloorSeconds))} - ${import_general.Duration.format((0, import_general.Seconds)(maxIntervalCeilingSeconds))} => ${import_general.Duration.format(subscription.maxInterval)}`,
        sendInterval: import_general.Duration.format(subscription.sendInterval)
      })
    );
    return subscription;
  }
  async establishFormerSubscription({
    subscriptionId,
    attributeRequests,
    eventRequests,
    isFabricFiltered,
    minIntervalFloor,
    maxIntervalCeiling,
    maxInterval,
    sendInterval
  }, session) {
    const exchange = this.#context.exchangeManager.initiateExchange(session.peerAddress, import_types.INTERACTION_PROTOCOL_ID);
    const message = {};
    logger.info(
      `Reestablish subscription \xBB`,
      exchange.via,
      import_general.Diagnostic.dict({
        subId: subscriptionId,
        isFabricFiltered,
        maxInterval: import_general.Duration.format(maxInterval),
        sendInterval: import_general.Duration.format(sendInterval)
      })
    );
    const context = {
      session,
      node: this.#node,
      initiateExchange: (address, protocolId) => this.#context.exchangeManager.initiateExchange(address, protocolId)
    };
    const subscription = new import_ServerSubscription.ServerSubscription({
      id: subscriptionId,
      context,
      minIntervalFloor,
      maxIntervalCeiling,
      criteria: {
        attributeRequests,
        eventRequests,
        isFabricFiltered
      },
      subscriptionOptions: this.#subscriptionConfig,
      useAsMaxInterval: maxInterval,
      useAsSendInterval: sendInterval
    });
    const readContext = this.#prepareOnlineContext(exchange, message, isFabricFiltered);
    try {
      await subscription.sendInitialReport(
        new import_protocol.InteractionServerMessenger(exchange),
        readContext,
        true
        // Do not send status responses because we simulate that the subscription is still established
      );
      subscription.activate();
      logger.info(
        `Subscription successfully reestablished \xBB`,
        exchange.via,
        import_general.Diagnostic.dict({
          subId: subscriptionId,
          timing: `${import_general.Duration.format(minIntervalFloor)} - ${import_general.Duration.format(maxIntervalCeiling)} => ${import_general.Duration.format(subscription.maxInterval)}`,
          sendInterval: import_general.Duration.format(subscription.sendInterval)
        })
      );
    } catch (error) {
      await subscription.close();
      throw error;
    }
    return subscription;
  }
  async handleInvokeRequest(exchange, request, messenger, message) {
    const { invokeRequests, timedRequest, suppressResponse, interactionModelRevision } = request;
    logger.info(() => [
      "Invoke \xAB",
      exchange.via,
      import_general.Diagnostic.asFlags({ suppressResponse, timedRequest }),
      import_general.Diagnostic.dict({
        invokes: invokeRequests.map(
          ({ commandPath: { endpointId, clusterId, commandId } }) => this.#node.protocol.inspectPath({ endpointId, clusterId, commandId })
        ).join(", ")
      })
    ]);
    if (interactionModelRevision > import_model.Specification.INTERACTION_MODEL_REVISION) {
      logger.debug(
        `Interaction model revision of sender ${interactionModelRevision} is higher than supported ${import_model.Specification.INTERACTION_MODEL_REVISION}.`
      );
    }
    const receivedWithinTimedInteraction = exchange.hasActiveTimedInteraction();
    if (exchange.hasExpiredTimedInteraction()) {
      exchange.clearTimedInteraction();
      throw new import_types.StatusResponseError(`Timed request window expired. Decline invoke request.`, import_types.StatusCode.Timeout);
    }
    if (timedRequest !== exchange.hasTimedInteraction()) {
      throw new import_types.StatusResponseError(
        `timedRequest flag of invoke interaction (${timedRequest}) mismatch with expected timed interaction (${receivedWithinTimedInteraction}).`,
        import_types.StatusCode.TimedRequestMismatch
      );
    }
    if (receivedWithinTimedInteraction) {
      logger.debug("Invoke request for timed interaction on", exchange.channel.name);
      exchange.clearTimedInteraction();
      if (message.packetHeader.sessionType !== import_protocol.SessionType.Unicast) {
        throw new import_types.StatusResponseError(
          "Invoke requests are only allowed on unicast sessions when a timed interaction is running.",
          import_types.StatusCode.InvalidAction
        );
      }
    }
    if (invokeRequests.length > this.#maxPathsPerInvoke) {
      throw new import_types.StatusResponseError(
        `Only ${this.#maxPathsPerInvoke} invoke requests are supported in one message. This message contains ${invokeRequests.length}`,
        import_types.StatusCode.InvalidAction
      );
    }
    const isGroupSession = message.packetHeader.sessionType === import_protocol.SessionType.Group;
    const invokeResponseMessage = {
      suppressResponse: false,
      // Deprecated but must be present
      interactionModelRevision: import_model.Specification.INTERACTION_MODEL_REVISION,
      invokeResponses: [],
      moreChunkedMessages: invokeRequests.length > 1
      // Assume for now we have multiple responses when having multiple invokes
    };
    const emptyInvokeResponseBytes = import_types.TlvInvokeResponseForSend.encode(invokeResponseMessage);
    let messageSize = emptyInvokeResponseBytes.byteLength;
    let invokeResultsProcessed = 0;
    const processResponseResult = async (invokeResponse) => {
      invokeResultsProcessed++;
      if (isGroupSession) {
        return;
      }
      const encodedInvokeResponse = import_types.TlvInvokeResponseData.encodeTlv(invokeResponse);
      const invokeResponseBytes = import_types.TlvAny.getEncodedByteLength(encodedInvokeResponse);
      if (messageSize + invokeResponseBytes > exchange.maxPayloadSize || invokeResultsProcessed === invokeRequests.length) {
        let lastMessageProcessed = false;
        if (messageSize + invokeResponseBytes <= exchange.maxPayloadSize) {
          invokeResponseMessage.invokeResponses.push(encodedInvokeResponse);
          lastMessageProcessed = true;
        }
        if (invokeResponseMessage.invokeResponses.length > 0) {
          if (invokeRequests.length > 1) {
            logger.debug(
              `${lastMessageProcessed ? "Final " : ""}Invoke response \xBB`,
              import_general.Diagnostic.dict({ commands: invokeResponseMessage.invokeResponses.length })
            );
          }
          const moreChunkedMessages = lastMessageProcessed ? void 0 : true;
          await messenger.send(
            import_protocol.MessageType.InvokeResponse,
            import_types.TlvInvokeResponseForSend.encode({
              ...invokeResponseMessage,
              moreChunkedMessages
            }),
            {
              logContext: {
                invokeMsgFlags: import_general.Diagnostic.asFlags({
                  suppressResponse,
                  moreChunkedMessages
                })
              }
            }
          );
          invokeResponseMessage.invokeResponses = [];
          messageSize = emptyInvokeResponseBytes.byteLength;
        }
        if (!lastMessageProcessed) {
          invokeResultsProcessed--;
          return processResponseResult(invokeResponse);
        }
      } else {
        invokeResponseMessage.invokeResponses.push(encodedInvokeResponse);
        messageSize += invokeResponseBytes;
      }
    };
    for await (const chunk of this.#serverInteraction.invoke(
      request,
      this.#prepareOnlineContext(exchange, message, void 0, receivedWithinTimedInteraction)
    )) {
      if (suppressResponse) {
        throw new import_general.InternalError("Received response that should be suppressed for invoke");
      }
      for (const data of chunk) {
        switch (data.kind) {
          case "cmd-response": {
            const { path: commandPath, commandRef, data: commandFields } = data;
            await processResponseResult({
              command: {
                commandPath,
                commandFields,
                commandRef
              }
            });
            break;
          }
          case "cmd-status": {
            const { path, commandRef, status, clusterStatus } = data;
            await processResponseResult({
              status: { commandPath: path, status: { status, clusterStatus }, commandRef }
            });
          }
        }
      }
    }
  }
  handleTimedRequest(exchange, { timeout, interactionModelRevision }) {
    const interval = (0, import_general.Millis)(timeout);
    logger.debug(() => [
      "Timed request \xAB",
      exchange.via,
      import_general.Diagnostic.dict({
        interval: import_general.Duration.format(interval)
      })
    ]);
    if (interactionModelRevision > import_model.Specification.INTERACTION_MODEL_REVISION) {
      logger.debug(
        `Interaction model revision of sender ${interactionModelRevision} is higher than supported ${import_model.Specification.INTERACTION_MODEL_REVISION}.`
      );
    }
    exchange.startTimedInteraction(interval);
  }
  async close() {
    this.#isClosing = true;
  }
}
//# sourceMappingURL=InteractionServer.js.map
