"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
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 __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
  // If the importer is in node compatibility mode or this is not an ESM
  // file that has been converted to a CommonJS file using a Babel-
  // compatible transform (i.e. "__esModule" has not been set), then set
  // "default" to the CommonJS "module.exports" for node compatibility.
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
  mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var Semantics_exports = {};
__export(Semantics_exports, {
  Semantics: () => Semantics
});
module.exports = __toCommonJS(Semantics_exports);
var import_errors = require("#decoration/errors.js");
var import_general = require("#general");
var models = __toESM(require("#standard/elements/models.js"), 1);
/**
 * @license
 * Copyright 2022-2025 Matter.js Authors
 * SPDX-License-Identifier: Apache-2.0
 */
const standardModels = new Set(Object.values(models));
class Semantics {
  #localModel;
  #isFinal = false;
  /**
   * Determine whether these semantics are final.
   *
   * Once final no further mutation is allowed.
   */
  get isFinal() {
    return this.#isFinal;
  }
  /**
   * Finalize the model.
   */
  finalize() {
    if (this.#isFinal) {
      return;
    }
    this.#isFinal = true;
    Object.freeze(this);
    this.#localModel?.finalize();
  }
  /**
   * The {@link Model} defined by local decoration, if any.
   */
  get localModel() {
    return this.#localModel;
  }
  /**
   * Set the model.
   *
   * When "setting" the model we need to merge semantics coming from decorators, the prototype hierarchy, and models
   * provided programmatically.
   *
   * This may set the local model, change it or set its operational base.  We use local state and the finalization
   * status of the model to determine how to integrate.
   */
  set mutableModel(model) {
    if (this.#isFinal) {
      throw new import_errors.MetadataConflictError(`Cannot modify final semantics of ${this.#localModel?.name ?? "(none)"}`);
    }
    if (this.#localModel === model) {
      return;
    }
    if (standardModels.has(model)) {
      model.finalize();
    }
    this.#localModel = this.integrateModel(model);
  }
  /**
   * Obtain a model unconditionally for mutation purposes.
   */
  get mutableModel() {
    if (this.#isFinal) {
      throw new import_errors.MetadataConflictError(`Cannot modify final semantics of ${this.#localModel?.name ?? "(none)"}`);
    }
    if (this.#localModel === void 0) {
      this.#localModel = this.createModel();
    } else if (this.#localModel.isFinal) {
      this.#localModel = this.#localModel.extend();
    }
    return this.#localModel;
  }
  /**
   * The model's {@link Model.Type}.
   *
   * Field decorators operate prior to class decorators, so we may need to transition the model to a new type when the
   * class is decorated.  This is slightly lossy so type-specific decoration should always occur after assigning kind.
   */
  get modelType() {
    if (this.#localModel === void 0) {
      return;
    }
    return this.mutableModel.constructor;
  }
  set modelType(type) {
    if (this.#localModel === void 0) {
      this.#localModel = this.createModel(type);
      return;
    }
    if (this.#localModel instanceof type) {
      return;
    }
    const original = this.#localModel;
    const { parent } = original;
    original.parent = void 0;
    const replacement = new type({
      name: original.name,
      id: original.id,
      type: original.type,
      parent,
      operationalBase: original.operationalBase,
      children: original.children
    });
    if ("quality" in original && "quality" in replacement) {
      replacement.quality = original.quality;
    }
    this.#localModel = replacement;
  }
}
((Semantics2) => {
  function of(context) {
    const classSemantics = (0, Semantics2.classOf)(context);
    if (context.kind === "class") {
      return classSemantics;
    }
    return classSemantics.fieldFor(context.name);
  }
  Semantics2.of = of;
  Semantics2.classOf = (_source) => {
    throw new import_general.InternalError(`Class decoration lookup not installed`);
  };
})(Semantics || (Semantics = {}));
//# sourceMappingURL=Semantics.js.map
