/**
 * @license
 * Copyright 2022-2026 Matter.js Authors
 * SPDX-License-Identifier: Apache-2.0
 */
import { SharedServicesManager } from "#environment/SharedServicesManager.js";
import { ImplementationError } from "#MatterError.js";
import { MaybePromise } from "#util/Promises.js";
class SharedEnvironmentServices {
  #env;
  #serviceTypes = /* @__PURE__ */ new Set();
  #closed = false;
  constructor(env) {
    this.#env = env;
  }
  #assertClosed() {
    if (this.#closed) {
      throw new ImplementationError("Dependent environment is closed");
    }
  }
  /** Check if this instance is currently tracking a specific service type. */
  has(type) {
    return this.#serviceTypes.has(type);
  }
  /**
   * Access an environmental service and register this instance as a consumer.
   *
   * The service will be tracked and protected from closure until this instance
   * explicitly releases it via {@link delete} or {@link close}.
   */
  get(type) {
    this.#assertClosed();
    const instance = this.#env.get(type);
    this.#serviceTypes.add(type);
    return instance;
  }
  /**
   * Access an optional environmental service and register this instance as a consumer.
   *
   * Returns undefined if the service is not available, otherwise behaves like {@link get}.
   */
  maybeGet(type) {
    this.#assertClosed();
    if (this.#env.has(type)) {
      return this.get(type);
    }
  }
  /**
   * Unregister this instance from a service and remove the service from the environment.
   *
   * If other consumers are still using the service, it remains available for them.
   * Only affects services this instance has accessed via {@link get} or {@link load}.
   */
  delete(type, instance) {
    this.#assertClosed();
    if (!this.#serviceTypes.has(type)) {
      return;
    }
    this.#serviceTypes.delete(type);
    this.#env.delete(type, instance);
  }
  /**
   * Load an environmental service asynchronously and register this instance as a consumer.
   *
   * Waits for the service's construction promise to resolve if present, then tracks the service for lifecycle
   * management.
   */
  async load(type) {
    this.#assertClosed();
    const instance = await this.#env.load(type);
    this.#serviceTypes.add(type);
    return instance;
  }
  close(type) {
    this.#assertClosed();
    if (type === void 0) {
      this.#closed = true;
      const types = Array.from(this.#serviceTypes);
      this.#serviceTypes.clear();
      const closePromises = new Array();
      for (const type2 of types) {
        const closer = this.#env.close(type2);
        if (MaybePromise.is(closer)) {
          closePromises.push(closer);
        }
      }
      this.#env.root.get(SharedServicesManager).delete(this);
      if (closePromises.length > 0) {
        return Promise.all(closePromises).then(() => void 0);
      }
    } else {
      if (!this.#serviceTypes.has(type)) {
        return;
      }
      this.#serviceTypes.delete(type);
      return this.#env.close(type);
    }
  }
  async [Symbol.asyncDispose]() {
    await this.close();
  }
}
export {
  SharedEnvironmentServices
};
//# sourceMappingURL=SharedEnvironmentServices.js.map
