/**
 * @license
 * Copyright 2022-2026 Matter.js Authors
 * SPDX-License-Identifier: Apache-2.0
 */
import { camelize, capitalize, decamelize } from "@matter/general";
import { ClusterModel, GeneratorScope, GLOBAL_IDS, Metatype, ValueModel } from "@matter/model";
import { StatusResponseError } from "../common/StatusResponseError.js";
import { ClusterId } from "../datatype/ClusterId.js";
import { Status } from "../globals/Status.js";
import { ClassForValueModel } from "./ClassForValueModel.js";
import { EnumForValueModel } from "./EnumForValueModel.js";
import { RetiredClusterType } from "./RetiredClusterType.js";
const cache = /* @__PURE__ */ new WeakMap();
function ClusterType(input) {
  const model = input instanceof ClusterModel ? input : RetiredClusterType.ModelForOptions(input);
  let ns = cache.get(model);
  if (ns !== void 0) {
    return ns;
  }
  ns = /* @__PURE__ */ Object.create(null);
  cache.set(model, ns);
  const props = ns;
  if (model.id !== void 0) {
    props.id = ClusterId(model.id);
  }
  props.name = model.name;
  props.revision = model.revision;
  props.schema = model;
  installLazyProperties(ns, model);
  return ns;
}
function installLazyProperties(ns, model) {
  const lazy = (name, factory) => {
    Object.defineProperty(ns, name, {
      get() {
        const value = factory();
        Object.defineProperty(ns, name, { value, enumerable: true, configurable: true });
        return value;
      },
      enumerable: true,
      configurable: true
    });
  };
  lazy("attributes", () => ClusterType.attributes(model));
  lazy("commands", () => ClusterType.commands(model));
  lazy("events", () => ClusterType.events(model));
  lazy("features", () => ClusterType.features(model));
  if (!Object.hasOwn(ns, "Cluster")) {
    lazy("Cluster", () => ns);
  }
  lazy("Complete", () => ns);
  if (model.features.length) {
    lazy("Feature", () => {
      const result = {};
      for (const f of model.features) {
        const name = camelize(f.title ?? f.name, true);
        result[name] = name;
      }
      return Object.freeze(result);
    });
  }
  installDatatypeGetters(model, lazy);
}
function installDatatypeGetters(model, lazy) {
  const scope = GeneratorScope(model);
  for (const [definer, name, location] of scope.namedModels()) {
    if (!location.isLocal || !(definer instanceof ValueModel)) {
      continue;
    }
    const metatype = definer.effectiveMetatype;
    if (metatype === Metatype.enum) {
      if (!definer.children.length) {
        continue;
      }
      lazy(name, () => EnumForValueModel(definer));
      if (definer.name === "StatusEnum" || definer.name === "StatusCodeEnum") {
        for (const field of definer.children) {
          if (field.name === "Success") {
            continue;
          }
          let errName = field.name;
          if (!errName.endsWith("Error")) {
            errName = `${errName}Error`;
          }
          lazy(errName, () => {
            let message = field.description;
            if (message === void 0) {
              message = capitalize(decamelize(field.name, " "));
            }
            if (message.endsWith(".")) {
              message = message.slice(0, message.length - 1);
            }
            const clusterCode = typeof field.id === "number" ? field.id : void 0;
            const defaultMessage = message;
            return {
              [errName]: class extends StatusResponseError {
                constructor(message2 = defaultMessage, code = Status.Failure, clusterCode2 = clusterCode) {
                  super(message2, code, clusterCode2);
                }
              }
            }[errName];
          });
        }
      }
    } else if (metatype === Metatype.object || metatype === Metatype.bitmap) {
      lazy(name, () => ClassForValueModel(definer));
    }
  }
}
((ClusterType2) => {
  ClusterType2.Unknown = {
    Typing: {},
    id: ClusterId(0),
    name: "Unknown",
    schema: new ClusterModel({ name: "Unknown" })
  };
  function attributes(model) {
    const result = {};
    for (const attribute of model.attributes) {
      if (GLOBAL_IDS.has(attribute.id) || attribute.isDisallowed || attribute.effectiveMetatype === void 0) {
        continue;
      }
      const key = attribute.propertyName;
      result[key] = {
        id: attribute.id,
        name: key,
        schema: attribute
      };
    }
    return result;
  }
  ClusterType2.attributes = attributes;
  function commands(model) {
    const result = {};
    for (const command of model.commands) {
      if (!command.isRequest || command.isDisallowed) {
        continue;
      }
      const key = command.propertyName;
      result[key] = {
        id: command.id,
        name: key,
        schema: command
      };
    }
    return result;
  }
  ClusterType2.commands = commands;
  function events(model) {
    const result = {};
    for (const event of model.events) {
      if (event.isDisallowed) {
        continue;
      }
      const key = event.propertyName;
      result[key] = {
        id: event.id,
        name: key,
        schema: event
      };
    }
    return result;
  }
  ClusterType2.events = events;
  function features(model) {
    const result = {};
    for (const feature of model.features) {
      const key = camelize(feature.title ?? feature.name);
      if (typeof feature.constraint.value === "number") {
        result[key] = {
          id: feature.constraint.value,
          name: key
        };
      }
    }
    return result;
  }
  ClusterType2.features = features;
})(ClusterType || (ClusterType = {}));
export {
  ClusterType
};
//# sourceMappingURL=ClusterType.js.map
