"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 RootSupervisor_exports = {};
__export(RootSupervisor_exports, {
  RootSupervisor: () => RootSupervisor
});
module.exports = __toCommonJS(RootSupervisor_exports);
var import_general = require("#general");
var import_model = require("#model");
var import_AccessControl = require("../AccessControl.js");
var import_ValueCaster = require("../state/managed/values/ValueCaster.js");
var import_ValueManager = require("../state/managed/values/ValueManager.js");
var import_ValuePatcher = require("../state/managed/values/ValuePatcher.js");
var import_ValueValidator = require("../state/validation/ValueValidator.js");
/**
 * @license
 * Copyright 2022-2024 Matter.js Authors
 * SPDX-License-Identifier: Apache-2.0
 */
const GlobalAttributeSupervisors = {};
const cache = /* @__PURE__ */ new WeakMap();
class RootSupervisor {
  #generating = /* @__PURE__ */ new Set();
  #cache = /* @__PURE__ */ new WeakMap();
  #featureMap;
  #supportedFeatures;
  #members;
  #root;
  #memberNames;
  #persistentNames;
  /**
   * Create a new supervisor.
   *
   * @param schema the {@link Schema} for the supervised data
   */
  constructor(schema) {
    schema.freeze();
    if (schema instanceof import_model.ClusterModel) {
      this.#featureMap = schema.featureMap;
      this.#supportedFeatures = schema.supportedFeatures ?? new import_model.FeatureSet();
    } else {
      this.#featureMap = new import_model.AttributeModel(import_model.FeatureMap);
      this.#supportedFeatures = new import_model.FeatureSet();
    }
    this.#members = new Set(schema.activeMembers);
    this.#root = this.#createValueSupervisor(schema);
  }
  /**
   * Obtain the supervisor for schema.  The result is cached.
   */
  static for(schema) {
    if (cache.has(schema)) {
      return cache.get(schema);
    }
    const supervisor = new RootSupervisor(schema);
    cache.set(schema, supervisor);
    return supervisor;
  }
  get owner() {
    return this.#root.owner;
  }
  get schema() {
    return this.#root.schema;
  }
  get access() {
    return this.#root.access;
  }
  get validate() {
    return this.#root.validate;
  }
  get manage() {
    return this.#root.manage;
  }
  get patch() {
    return this.#root.patch;
  }
  get cast() {
    return this.#root.cast;
  }
  /**
   * The names of all members.
   */
  get memberNames() {
    let names = this.#memberNames;
    if (!names) {
      names = /* @__PURE__ */ new Set();
      for (const member of this.#members) {
        names.add((0, import_general.camelize)(member.name));
      }
      this.#memberNames = names;
    }
    return names;
  }
  /**
   * Names of fields configured as non-volatile.
   */
  get persistentNames() {
    let persistent = this.#persistentNames;
    if (!persistent) {
      persistent = /* @__PURE__ */ new Set();
      for (const member of this.#members) {
        if (member.effectiveQuality.nonvolatile || member.effectiveAccess.writable || member.effectiveAccess.fabricScoped) {
          persistent.add((0, import_general.camelize)(member.name));
        }
      }
      this.#persistentNames = persistent;
    }
    return persistent;
  }
  /**
   * All available features defined in the schema.
   */
  get featureMap() {
    return this.#featureMap;
  }
  /**
   * Features supported by this implementation.
   */
  get supportedFeatures() {
    return this.#supportedFeatures;
  }
  /**
   * Obtain {@link ValueSupervisor} implementation for a specific schema.
   *
   * @param schema the model describing the record type
   * @returns the I/O implementation
   */
  get(schema) {
    if (schema === this.#root?.schema) {
      return this;
    }
    let supervisor = this.#cache.get(schema);
    if (supervisor === void 0) {
      if (schema.tag === "attribute" && schema.id !== void 0 && schema.id in GlobalAttributeSupervisors) {
        supervisor = {
          ...GlobalAttributeSupervisors[schema.id],
          owner: this,
          schema
        };
      } else {
        supervisor = this.#createValueSupervisor(schema);
      }
      this.#cache.set(schema, supervisor);
    }
    return supervisor;
  }
  #createValueSupervisor(schema) {
    const deferGeneration = (name, generator) => {
      let generated = false;
      return (...args) => {
        if (!generated) {
          if (manager === void 0) {
            throw new import_general.InternalError("Deferred I/O generation invoked impossibly early");
          }
          manager[name] = generator(schema, this);
          generated = true;
        }
        return manager[name](...args);
      };
    };
    let manager;
    if (this.#isGenerating(schema)) {
      manager = {
        owner: this,
        schema,
        access: (0, import_AccessControl.AccessControl)(schema),
        validate: deferGeneration("validate", import_ValueValidator.ValueValidator),
        manage: deferGeneration("manage", import_ValueManager.ValueManager),
        patch: deferGeneration("patch", import_ValuePatcher.ValuePatcher),
        cast: deferGeneration("cast", import_ValueCaster.ValueCaster)
      };
    } else {
      try {
        this.#generating.add(schema);
        manager = {
          owner: this,
          schema,
          access: (0, import_AccessControl.AccessControl)(schema),
          validate: (0, import_ValueValidator.ValueValidator)(schema, this),
          manage: (0, import_ValueManager.ValueManager)(schema, this),
          patch: (0, import_ValuePatcher.ValuePatcher)(schema, this),
          cast: (0, import_ValueCaster.ValueCaster)(schema, this)
        };
      } finally {
        this.#generating.delete(schema);
      }
    }
    this.#cache.set(schema, manager);
    return manager;
  }
  /**
   * If a schema has circular references, code generation may need to defer generation of child functions to avoid
   * infinite loops.
   *
   * In order to keep generation code simpler we use this method to detect when lazy generation is necessary and
   * install stubs that bootstrap each method.
   */
  #isGenerating(schema) {
    return this.#generating.has(schema);
  }
}
const PrototypicalCluster = new import_model.ClusterModel({ name: "Prototype" });
for (const attribute of import_model.Matter.all(import_model.AttributeModel)) {
  if (attribute.id === void 0) {
    continue;
  }
  PrototypicalCluster.children.push(attribute.clone());
}
const GlobalSupervisor = new RootSupervisor(PrototypicalCluster);
for (const attribute of PrototypicalCluster.children) {
  if (attribute.id === void 0 || attribute.id === import_model.FeatureMap.id) {
    continue;
  }
  GlobalAttributeSupervisors[attribute.id] = GlobalSupervisor.get(attribute);
}
//# sourceMappingURL=RootSupervisor.js.map
