"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 SecureChannelMessenger_exports = {};
__export(SecureChannelMessenger_exports, {
  ChannelStatusResponseError: () => ChannelStatusResponseError,
  DEFAULT_NORMAL_PROCESSING_TIME: () => DEFAULT_NORMAL_PROCESSING_TIME,
  EXPECTED_CRYPTO_PROCESSING_TIME: () => EXPECTED_CRYPTO_PROCESSING_TIME,
  SecureChannelMessenger: () => SecureChannelMessenger
});
module.exports = __toCommonJS(SecureChannelMessenger_exports);
var import_general = require("#general");
var import_types = require("#types");
var import_SecureChannelStatusMessageSchema = require("./SecureChannelStatusMessageSchema.js");
/**
 * @license
 * Copyright 2022-2026 Matter.js Authors
 * SPDX-License-Identifier: Apache-2.0
 */
class ChannelStatusResponseError extends import_general.MatterError {
  constructor(message, generalStatusCode, protocolStatusCode) {
    super(
      `(${import_types.GeneralStatusCode[generalStatusCode]} (${generalStatusCode}) / ${import_types.SecureChannelStatusCode[protocolStatusCode]} (${protocolStatusCode})) ${message}`
    );
    this.generalStatusCode = generalStatusCode;
    this.protocolStatusCode = protocolStatusCode;
  }
}
const EXPECTED_CRYPTO_PROCESSING_TIME = (0, import_general.Seconds)(30);
const DEFAULT_NORMAL_PROCESSING_TIME = (0, import_general.Seconds)(2);
class SecureChannelMessenger {
  constructor(exchange, defaultExpectedProcessingTime = EXPECTED_CRYPTO_PROCESSING_TIME) {
    this.exchange = exchange;
    this.#defaultExpectedProcessingTime = defaultExpectedProcessingTime;
  }
  #defaultExpectedProcessingTime;
  get channel() {
    return this.exchange.channel;
  }
  async nextMessage(expectedMessageType, expectedProcessingTimeMs = this.#defaultExpectedProcessingTime, expectedMessageInfo) {
    return this.#nextMessage(expectedMessageType, expectedProcessingTimeMs, expectedMessageInfo);
  }
  async anyNextMessage(expectedMessageInfo, expectedProcessingTime = this.#defaultExpectedProcessingTime) {
    return this.#nextMessage(void 0, expectedProcessingTime, expectedMessageInfo);
  }
  /**
   * Waits for the next message and returns it.
   *
   * When no expectedProcessingTimeMs is provided, the default value of EXPECTED_CRYPTO_PROCESSING_TIME_MS is used.
   */
  async #nextMessage(expectedMessageType, expectedProcessingTime = this.#defaultExpectedProcessingTime, expectedMessageInfo) {
    const message = await this.exchange.nextMessage({ expectedProcessingTime });
    const messageType = message.payloadHeader.messageType;
    if (expectedMessageType !== void 0 && expectedMessageInfo === void 0) {
      expectedMessageInfo = import_types.SecureMessageType[expectedMessageType];
    }
    this.throwIfErrorStatusReport(message, expectedMessageInfo);
    if (expectedMessageType !== void 0 && messageType !== expectedMessageType)
      throw new import_general.UnexpectedDataError(
        `Received unexpected message type: ${messageType}, expected: ${expectedMessageType} (${expectedMessageInfo})`
      );
    return message;
  }
  /**
   * Waits for the next message and decodes it.
   *
   * When no expectedProcessingTimeMs is provided, the default value of EXPECTED_CRYPTO_PROCESSING_TIME_MS is used.
   */
  async nextMessageDecoded(expectedMessageType, schema, expectedProcessingTime = this.#defaultExpectedProcessingTime) {
    return schema.decode((await this.nextMessage(expectedMessageType, expectedProcessingTime)).payload);
  }
  /**
   * Waits for the next message and returns it.
   *
   * When no expectedProcessingTimeMs is provided, the default value of EXPECTED_CRYPTO_PROCESSING_TIME_MS is used.
   */
  async waitForSuccess(expectedMessageInfo, expectedProcessingTime = this.#defaultExpectedProcessingTime) {
    await this.nextMessage(import_types.SecureMessageType.StatusReport, expectedProcessingTime, expectedMessageInfo);
  }
  /**
   * Sends a message of the given type with the given payload.
   *
   * If no ExchangeSendOptions are provided, the expectedProcessingTimeMs will be set to
   * EXPECTED_CRYPTO_PROCESSING_TIME_MS.
   */
  async send(message, type, schema, options) {
    options = {
      ...options,
      expectedProcessingTime: options?.expectedProcessingTime ?? this.#defaultExpectedProcessingTime
    };
    const payload = schema.encode(message);
    await this.exchange.send(type, payload, options);
    return payload;
  }
  sendError(code) {
    return this.#sendStatusReport(import_types.GeneralStatusCode.Failure, code);
  }
  sendSuccess() {
    return this.#sendStatusReport(import_types.GeneralStatusCode.Success, import_types.SecureChannelStatusCode.Success);
  }
  sendCloseSession() {
    return this.#sendStatusReport(import_types.GeneralStatusCode.Success, import_types.SecureChannelStatusCode.CloseSession, false);
  }
  get channelName() {
    return this.exchange.channel.channel.name;
  }
  [Symbol.asyncDispose]() {
    return this.close();
  }
  async close() {
    await this.exchange.close();
  }
  async #sendStatusReport(generalStatus, protocolStatus, requiresAck) {
    await this.exchange.send(
      import_types.SecureMessageType.StatusReport,
      import_SecureChannelStatusMessageSchema.SecureChannelStatusMessage.encode({
        generalStatus,
        protocolStatus
      }),
      {
        requiresAck,
        logContext: {
          generalStatus: import_types.GeneralStatusCode[generalStatus] ?? import_general.Diagnostic.hex(generalStatus),
          protocolStatus: import_types.SecureChannelStatusCode[protocolStatus] ?? import_general.Diagnostic.hex(protocolStatus)
        }
      }
    );
  }
  throwIfErrorStatusReport(message, logHint) {
    const {
      payloadHeader: { messageType },
      payload
    } = message;
    if (messageType !== import_types.SecureMessageType.StatusReport) return;
    const { generalStatus, protocolId, protocolStatus } = import_SecureChannelStatusMessageSchema.SecureChannelStatusMessage.decode(payload);
    if (generalStatus !== import_types.GeneralStatusCode.Success) {
      throw new ChannelStatusResponseError(
        `Received general error status for protocol ${protocolId}${logHint ? ` (${logHint})` : ""}`,
        generalStatus,
        protocolStatus
      );
    }
    if (protocolStatus !== import_types.SecureChannelStatusCode.Success) {
      throw new ChannelStatusResponseError(
        `Received general success status, but protocol status is not Success${logHint ? ` (${logHint})` : ""}`,
        generalStatus,
        protocolStatus
      );
    }
  }
}
//# sourceMappingURL=SecureChannelMessenger.js.map
