"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 Api_exports = {};
__export(Api_exports, {
  Api: () => Api
});
module.exports = __toCommonJS(Api_exports);
var import_general = require("#general");
var import_Node = require("#node/Node.js");
var import_protocol = require("#protocol");
var import_types = require("#types");
var import_ApiPath = require("./ApiPath.js");
var import_RemoteResponse = require("./RemoteResponse.js");
var import_EndpointResource = require("./resources/EndpointResource.js");
var import_NodeResource = require("./resources/NodeResource.js");
var import_ServerNodeResource = require("./resources/ServerNodeResource.js");
/**
 * @license
 * Copyright 2022-2026 Matter.js Authors
 * SPDX-License-Identifier: Apache-2.0
 */
const loggers = /* @__PURE__ */ new Map();
var Api;
((Api2) => {
  async function resourceFor(agent, path) {
    let item;
    if ("peers" in agent.endpoint) {
      item = new import_ServerNodeResource.ServerNodeResource(agent, void 0);
    } else if (agent.endpoint instanceof import_Node.Node) {
      item = new import_NodeResource.NodeResource(agent, void 0);
    } else {
      item = new import_EndpointResource.EndpointResource(agent, void 0);
    }
    const breadcrumb = [item];
    for (const segment of path) {
      const parent = breadcrumb[breadcrumb.length - 1];
      const item2 = await parent.childFor(segment);
      if (!item2) {
        return;
      }
      breadcrumb.push(item2);
    }
    return breadcrumb[breadcrumb.length - 1];
  }
  Api2.resourceFor = resourceFor;
  function log(level, facility, id, ...message) {
    let logger = loggers.get(facility);
    if (!logger) {
      loggers.set(facility, logger = import_general.Logger.get(facility));
    }
    logger[level](import_general.Diagnostic.via(id || "(anon)"), message);
  }
  Api2.log = log;
  function logRequest(facility, id, method, target) {
    log("info", facility, id, import_protocol.Mark.INBOUND, import_general.Diagnostic.strong(method), target);
  }
  Api2.logRequest = logRequest;
  function logResponse(facility, response) {
    const message = Array(import_protocol.Mark.OUTBOUND, import_RemoteResponse.RemoteResponse.describe(response));
    let level;
    switch (response.kind) {
      case "error":
        message.push(import_general.Diagnostic.errorMessage({ id: response.code, message: response.message }));
        level = "error";
        break;
      default:
        level = "info";
        break;
    }
    log(level, facility, response.id, message);
  }
  Api2.logResponse = logResponse;
  async function execute(facility, node, request, signal) {
    const { target, method, id } = request;
    logRequest(facility, id, method, target);
    try {
      const message = await node.act("remote", async (agent) => {
        const item = await resourceFor(agent, new import_ApiPath.ApiPath(target));
        if (item === void 0) {
          throw new import_types.StatusResponse.NotFoundError(`Target "${target}" not found`);
        }
        switch (method) {
          case "read":
            const value = item.read();
            if (value === void 0) {
              throw new import_types.StatusResponse.UnsupportedReadError(`Target "${target}" is not readable`);
            }
            value.convertToJson();
            return {
              kind: "value",
              id,
              // TODO - consider handling serialization here (in agent context) so copy is unnecessary
              value
            };
          case "write":
            item.write({ js: request.value });
            return { kind: "ok", id };
          case "add":
            item.add({ js: item.value });
            return { kind: "ok", id };
          case "delete":
            item.delete();
            return { kind: "ok", id };
          case "invoke": {
            const value2 = await item.invoke({ js: request.parameters });
            if (value2?.js === void 0 || value2?.js === null) {
              return { kind: "ok", id };
            }
            value2.convertToJson();
            return { id, kind: "value", value: value2 };
          }
          case "subscribe": {
            const options = { ...request };
            for (const field of ["target", "id", "method"]) {
              delete options[field];
            }
            const stream = item.subscribe(signal, {
              id,
              js: options
            });
            return { kind: "subscription", id, stream };
          }
        }
      });
      return message;
    } catch (error) {
      return errorResponseOf(facility, id, error);
    }
  }
  Api2.execute = execute;
  function errorResponseOf(facility, id, error) {
    error = (0, import_general.asError)(error);
    if (error instanceof import_types.StatusResponseError) {
      return { kind: "error", id, error };
    }
    log("error", facility, id, "Internal error:", error);
    return { kind: "error", id, error: new import_general.InternalError() };
  }
  Api2.errorResponseOf = errorResponseOf;
})(Api || (Api = {}));
//# sourceMappingURL=Api.js.map
