var __knownSymbol = (name, symbol) => (symbol = Symbol[name]) ? symbol : /* @__PURE__ */ Symbol.for("Symbol." + name);
var __typeError = (msg) => {
  throw TypeError(msg);
};
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();
};
/**
 * @license
 * Copyright 2022-2026 Matter.js Authors
 * SPDX-License-Identifier: Apache-2.0
 */
import { CommissioningServer } from "#behavior/system/commissioning/CommissioningServer.js";
import { EventsBehavior } from "#behavior/system/events/EventsBehavior.js";
import { NetworkServer } from "#behavior/system/network/NetworkServer.js";
import { ServerNetworkRuntime } from "#behavior/system/network/ServerNetworkRuntime.js";
import { ProductDescriptionServer } from "#behavior/system/product-description/ProductDescriptionServer.js";
import { SessionsBehavior } from "#behavior/system/sessions/SessionsBehavior.js";
import { SubscriptionsBehavior } from "#behavior/system/subscriptions/SubscriptionsServer.js";
import { asyncNew, Construction, DiagnosticSource, errorOf, MatterError } from "#general";
import { FabricManager, OccurrenceManager, ServerInteraction, SessionManager } from "#protocol";
import { ServerNodeStore } from "#storage/server/ServerNodeStore.js";
import { RootEndpoint as BaseRootEndpoint } from "../endpoints/root.js";
import { Node } from "./Node.js";
import { Peers } from "./client/Peers.js";
import { ServerEnvironment } from "./server/ServerEnvironment.js";
class FactoryResetError extends MatterError {
  constructor(message, cause) {
    super(message);
    this.cause = errorOf(cause);
  }
}
class ServerNode extends Node {
  #peers;
  #interaction;
  constructor(definition, options) {
    super(Node.nodeConfigFor(ServerNode.RootEndpoint, definition, options ?? {}));
    this.env.set(Node, this);
    this.env.set(ServerNode, this);
    DiagnosticSource.add(this);
    this.construction.start();
  }
  static async create(definition, options) {
    return await asyncNew(this, definition, options);
  }
  createRuntime() {
    return new ServerNetworkRuntime(this);
  }
  async [Construction.destruct]() {
    if (this.#peers) {
      await this.#peers.close();
    }
    await super[Construction.destruct]();
    await ServerEnvironment.close(this);
  }
  async prepareRuntimeShutdown() {
    await this.env.get(SessionManager).closeAllSessions();
  }
  /**
   * Perform a factory reset of the node.
   */
  async erase() {
    var _stack = [];
    try {
      const _erasing = __using(_stack, this.construction.join("erasing"));
      await this.lifecycle.mutex.produce(this.eraseWithMutex.bind(this));
    } catch (_) {
      var _error = _, _hasError = true;
    } finally {
      __callDispose(_stack, _error, _hasError);
    }
  }
  async eraseWithMutex() {
    try {
      await this.construction;
      const isOnline = this.lifecycle.isOnline;
      if (isOnline) {
        await this.cancelWithMutex();
      }
      this.statusUpdate("resetting to factory defaults");
      await this.resetWithMutex();
      await this.resetStorage();
      this.construction.start();
      if (isOnline && this.lifecycle.shouldBeOnline) {
        await this.startWithMutex();
      } else {
        await this.construction.ready;
      }
    } catch (e) {
      this.construction.crash();
      throw new FactoryResetError(`Error during factory reset of ${this}`, e);
    }
  }
  /**
   * Access other nodes on the fabric.
   */
  get peers() {
    if (!this.#peers) {
      try {
        this.#peers = new Peers(this);
        this.#peers.initialize();
      } catch (e) {
        this.#peers = void 0;
        throw e;
      }
    }
    return this.#peers;
  }
  get interaction() {
    if (this.#interaction === void 0) {
      this.#interaction = new ServerInteraction(this.protocol);
    }
    return this.#interaction;
  }
  async initialize() {
    await ServerEnvironment.initialize(this);
    await super.initialize();
  }
  /**
   * By default, on factory reset we erase all stored data.
   *
   * If this is inappropriate for your application, you may override to alter the behavior.  Matter requires that all
   * "security- and privacy-related data and key material" is removed on factory reset.
   *
   * @see {@link MatterSpecification.v12.Core} § 13.4
   */
  async resetStorage() {
    await this.env.get(SessionManager).clear();
    await this.env.get(FabricManager).clear();
    await this.env.get(OccurrenceManager).clear();
    await this.env.get(ServerNodeStore).erase();
  }
  /**
   * Normal endpoints must have an owner to complete construction but server nodes have no such precondition for
   * construction.
   */
  assertConstructable() {
  }
}
((ServerNode2) => {
  ServerNode2.RootEndpoint = BaseRootEndpoint.with(
    CommissioningServer,
    NetworkServer,
    ProductDescriptionServer,
    SubscriptionsBehavior,
    SessionsBehavior,
    EventsBehavior
  );
})(ServerNode || (ServerNode = {}));
Object.freeze(ServerNode.RootEndpoint);
export {
  ServerNode
};
//# sourceMappingURL=ServerNode.js.map
