"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 Plugins_exports = {};
__export(Plugins_exports, {
  Plugins: () => Plugins
});
module.exports = __toCommonJS(Plugins_exports);
var import_Behavior = require("#behavior/Behavior.js");
var import_Endpoint = require("#endpoint/Endpoint.js");
var import_general = require("@matter/general");
var import_load = require("@matter/node/load");
/**
 * @license
 * Copyright 2022-2026 Matter.js Authors
 * SPDX-License-Identifier: Apache-2.0
 */
const logger = import_general.Logger.get("Plugins");
class Plugins {
  #node;
  constructor(node) {
    this.#node = node;
  }
  /**
   * Load and apply all plugins.  Called once during node initialization.
   */
  async load() {
    const specifiers = Array();
    for (const path of ["plugins", `nodes.${this.#node.id}.plugins`]) {
      const value = this.#node.env.vars.get(path);
      if (typeof value === "string" && value.length) {
        for (const segment of value.split(",")) {
          const trimmed = segment.trim();
          if (trimmed.length && !specifiers.includes(trimmed)) {
            specifiers.push(trimmed);
          }
        }
      }
    }
    for (const specifier of specifiers) {
      const mod = await this.#loadModule(specifier);
      this.#applyModule(specifier, mod);
    }
  }
  async #loadModule(specifier) {
    try {
      const mod = (0, import_load.load)(specifier);
      if (import_general.MaybePromise.is(mod)) {
        return await mod;
      }
      return mod;
    } catch (e) {
      throw new import_general.ImportError(`Failed to load plugin "${specifier}": ${e}`);
    }
  }
  #applyModule(specifier, mod) {
    if (typeof mod.install === "function") {
      const result = mod.install(this.#node);
      if (import_general.MaybePromise.is(result)) {
        throw new import_general.ImportError(
          `Plugin "${specifier}" install function returned a promise; install must be synchronous`
        );
      }
      return;
    }
    const serverBehaviors = Array();
    const deviceTypes = Array();
    for (const [name, value] of Object.entries(mod)) {
      if (name === "default" || name.startsWith("_") || value === void 0 || value === null) {
        continue;
      }
      if (name.endsWith("Server") && isBehaviorType(value)) {
        serverBehaviors.push(value);
      } else if (isEndpointType(value)) {
        deviceTypes.push(value);
      }
    }
    if (serverBehaviors.length === 0 && deviceTypes.length === 0) {
      logger.debug("Plugin", specifier, "loaded (side-effect only)");
      return;
    }
    for (const behavior of serverBehaviors) {
      logger.debug("Plugin", specifier, "installing behavior", behavior.id);
      this.#node.behaviors.require(behavior);
    }
    if (deviceTypes.length > 1) {
      const names = deviceTypes.map((d) => `DeviceType "${d.name}"`);
      throw new import_general.ImportError(
        `Plugin "${specifier}" exports multiple device types (${names.join(", ")}). Add a named "install" export to specify how the plugin should be applied.`
      );
    }
    if (deviceTypes.length === 1) {
      logger.debug("Plugin", specifier, "adding endpoint", deviceTypes[0].name);
      this.#node.parts.add(new import_Endpoint.Endpoint(deviceTypes[0]));
    }
  }
}
function isBehaviorType(value) {
  return typeof value === "function" && value.prototype instanceof import_Behavior.Behavior;
}
function isEndpointType(value) {
  if (typeof value !== "object" || value === null) {
    return false;
  }
  const candidate = value;
  return typeof candidate.name === "string" && typeof candidate.deviceType === "number" && typeof candidate.deviceRevision === "number" && typeof candidate.behaviors === "object" && candidate.behaviors !== null;
}
//# sourceMappingURL=Plugins.js.map
