/**
 * @license
 * Copyright 2022-2026 Matter.js Authors
 * SPDX-License-Identifier: Apache-2.0
 */
import { InvalidMetadataError, MetadataConflictError } from "#decoration/errors.js";
import { FieldSemantics } from "#decoration/semantics/FieldSemantics.js";
import { Semantics } from "#decoration/semantics/Semantics.js";
import { CommandModel } from "#models/CommandModel.js";
import { Model } from "#models/Model.js";
import { Schema } from "#models/Schema.js";
import { Decorator } from "@matter/general";
function element(kind, ...modifiers) {
  let modelType;
  if (kind.Tag === "response") {
    modelType = CommandModel;
  } else {
    modelType = kind;
  }
  const forceType = !(modifiers[0] instanceof modelType);
  return Decorator((target, context) => {
    let semantics = Semantics.of(context);
    if (kind.Tag === "response") {
      semantics.modelType = CommandModel;
      if (semantics.response === void 0) {
        if (typeof context.name !== "string") {
          throw new InvalidMetadataError(
            `Cannot specify response for ${String(context.name) || "(anonymous)"} because element name is ${typeof context.name}`
          );
        }
        const response = new FieldSemantics(semantics.owner, context.name);
        response.modelType = CommandModel;
        response.mutableModel.name = `${context.name}Response`;
        response.mutableModel.isResponse = true;
        semantics = semantics.response = response;
      }
    }
    if (forceType) {
      semantics.modelType = modelType;
    }
    if (context.kind === "class") {
      semantics.new = target;
    }
    let result = void 0;
    for (const modifier of modifiers) {
      switch (typeof modifier) {
        case "number":
          semantics.mutableModel.id = modifier;
          continue;
        case "string":
          semantics.mutableModel.name = modifier;
          continue;
        case "function":
          if ("Tag" in modifier) {
            semantics.modelType = modifier;
          } else if (Decorator.is(modifier)) {
            const subresult = modifier(target, context);
            if (subresult) {
              if (result) {
                throw new MetadataConflictError(
                  `Multiple modifiers returned a value for ${String(context.name || "(anonymous)")}`
                );
              }
              result = subresult;
            }
          } else {
            const model = Schema(modifier);
            if (model === void 0) {
              throw new InvalidMetadataError(
                `Cannot use undecorated class ${modifier.name || "(anonymous)"} as type for ${String(context.name || "(anonymous)")}`
              );
            }
            model.finalize();
            semantics.mutableModel = model;
          }
          continue;
        case "object":
          if (modifier instanceof Model) {
            semantics.mutableModel = modifier;
            continue;
          }
          {
            const model = Schema(modifier);
            if (model !== void 0) {
              model.finalize();
              semantics.mutableModel = model;
              continue;
            }
          }
          break;
      }
      throw new InvalidMetadataError(
        `Unsupported modifier ${modifier} for ${String(context.name || "(anonymous)")}`
      );
    }
    return result;
  });
}
((element2) => {
  function property(kind) {
    return (...modifiers) => {
      return element2(kind, ...modifiers);
    };
  }
  element2.property = property;
  function klass(kind) {
    return (...modifiers) => {
      return element2(kind, ...modifiers);
    };
  }
  element2.klass = klass;
})(element || (element = {}));
export {
  element
};
//# sourceMappingURL=element.js.map
