"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 ClusterModel_exports = {};
__export(ClusterModel_exports, {
  ClusterModel: () => ClusterModel
});
module.exports = __toCommonJS(ClusterModel_exports);
var import_ModelTraversal = require("#logic/ModelTraversal.js");
var import_general = require("@matter/general");
var import_Access = require("../aspects/Access.js");
var import_Quality = require("../aspects/Quality.js");
var import_errors = require("../common/errors.js");
var import_common = require("../common/index.js");
var import_elements = require("../elements/index.js");
var import_definitions = require("../standard/elements/definitions.js");
var import_AttributeModel = require("./AttributeModel.js");
var import_Model = require("./Model.js");
var import_ScopeModel = require("./ScopeModel.js");
/**
 * @license
 * Copyright 2022-2026 Matter.js Authors
 * SPDX-License-Identifier: Apache-2.0
 */
class ClusterModel extends import_ScopeModel.ScopeModel {
  tag = import_elements.ClusterElement.Tag;
  classification;
  #quality;
  get diagnostics() {
    return this.effectiveQuality.diagnostics;
  }
  get quality() {
    return this.#quality;
  }
  set quality(definition) {
    this.#quality = import_Quality.Quality.create(definition);
  }
  get effectiveQuality() {
    return new import_ModelTraversal.ModelTraversal().findAspect(this, "quality", import_Quality.Quality) ?? this.#quality;
  }
  get attributes() {
    return this.scope.membersOf(this, { tags: [import_common.ElementTag.Attribute] });
  }
  get commands() {
    return this.scope.membersOf(this, { tags: [import_common.ElementTag.Command] });
  }
  get events() {
    return this.scope.membersOf(this, { tags: [import_common.ElementTag.Event] });
  }
  get datatypes() {
    return this.scope.membersOf(this, { tags: [import_common.ElementTag.Datatype] });
  }
  /**
   * Fields on a cluster are not part of the standard Matter data model.  They are used for internal extensions that
   * should not be served via the Matter protocol.
   */
  get fields() {
    return this.scope.membersOf(this, { tags: [import_common.ElementTag.Field] });
  }
  /**
   * Attributes and fields, for treating a cluster as a struct.
   */
  get properties() {
    return this.scope.membersOf(this, {
      tags: [import_common.ElementTag.Attribute, import_common.ElementTag.Field]
    });
  }
  get conformant() {
    return new ClusterModel.Conformant(this);
  }
  get pics() {
    return this.hasLocalResource ? this.localResource.pics : void 0;
  }
  set pics(pics) {
    if (pics || this.hasLocalResource) {
      this.localResource.pics = pics;
    }
  }
  /**
   * Get attributes, commands and events whether inherited or defined directly in this model.
   */
  get allAces() {
    return this.scope.membersOf(this, {
      tags: [import_common.ElementTag.Attribute, import_common.ElementTag.Command, import_common.ElementTag.Event]
    });
  }
  get revision() {
    let revision = 1;
    const revisionAttr = this.attributes(import_definitions.ClusterRevision.id);
    if (typeof revisionAttr?.default === "number") {
      revision = revisionAttr.default;
    }
    return revision;
  }
  get features() {
    const features = /* @__PURE__ */ new Map();
    new import_ModelTraversal.ModelTraversal().visitInheritance(this.featureMap, (model) => {
      for (const child of model.children) {
        if (child.tag !== "field") {
          continue;
        }
        if (features.has(child.name)) {
          continue;
        }
        features.set(child.name, child);
      }
    });
    return [...features.values()];
  }
  get featureMap() {
    return new import_ModelTraversal.ModelTraversal().findMember(this, import_definitions.FeatureMap.id, [import_common.ElementTag.Attribute]) ?? new import_AttributeModel.AttributeModel(import_definitions.FeatureMap);
  }
  get definedFeatures() {
    return new import_common.FeatureSet(this.features.map((feature) => feature.name));
  }
  get supportedFeatures() {
    const supported = {};
    for (const feature of this.features) {
      if (feature.default) {
        supported[feature.name] = true;
      }
    }
    return new import_common.FeatureSet(supported);
  }
  set supportedFeatures(features) {
    const featureSet = new import_common.FeatureSet(features);
    let featureMap = this.featureMap;
    if (featureMap.parent !== this) {
      featureMap = featureMap.clone();
      this.children.push(featureMap);
    }
    for (let feature of this.features) {
      const desc = feature.title && (0, import_general.camelize)(feature.title);
      let isSupported;
      if (desc !== void 0 && featureSet.has(desc)) {
        isSupported = true;
        featureSet.delete(desc);
      } else if (featureSet.has(feature.name)) {
        isSupported = true;
        featureSet.delete(feature.name);
      }
      if (!!feature.default === isSupported) {
        continue;
      }
      if (feature.parent !== featureMap) {
        feature = feature.clone();
        featureMap.children.push(feature);
      }
      feature.default = isSupported ? true : void 0;
    }
    if (featureSet.size) {
      throw new import_errors.SchemaImplementationError(
        this,
        `Cannot set unknown feature${featureSet.size > 1 ? "s" : ""} ${(0, import_general.describeList)("and", ...featureSet)}`
      );
    }
  }
  get effectiveMetatype() {
    return import_common.Metatype.object;
  }
  get effectiveAccess() {
    return import_Access.Access.Default;
  }
  constructor(definition, ...children) {
    super(definition, ...children);
    this.#quality = import_Quality.Quality.create(definition.quality);
    this.classification = definition.classification;
    if (!(definition instanceof import_Model.Model)) {
      this.pics = definition.pics;
    }
  }
  toElement(omitResources = false, extra) {
    return super.toElement(omitResources, {
      quality: this.quality.valueOf(),
      classification: this.classification,
      ...extra
    });
  }
  static Tag = import_elements.ClusterElement.Tag;
}
ClusterModel.register();
((ClusterModel2) => {
  class Conformant {
    #model;
    constructor(model) {
      this.#model = model;
    }
    /**
     * The cluster's conformant attributes.
     */
    get attributes() {
      return this.#model.scope.membersOf(this.#model, {
        tags: [import_common.ElementTag.Attribute],
        conformance: "conformant"
      });
    }
    /**
     * The cluster's conformant properties (includes fields and attributes).
     *
     * This offers compatibility with the equivalent field for ValueModel.  It is useful when treating a cluster as
     * a struct.
     */
    get properties() {
      return this.#model.scope.membersOf(this.#model, {
        tags: [import_common.ElementTag.Attribute, import_common.ElementTag.Field],
        conformance: "conformant"
      });
    }
    /**
     * The cluster's conformant fields.
     *
     * Fields are not formally allowed on clusters but we allow for extensions that should not be served via the
     * Matter protocol.
     *
     * This is primarily here to allow simplified access to fields in contexts where a variable is typed as a
     * ClusterModel or ValueModel.
     */
    get fields() {
      return this.#model.scope.membersOf(this.#model, {
        tags: [import_common.ElementTag.Field],
        conformance: "conformant"
      });
    }
    /**
     * The cluster's conformant commands.
     */
    get commands() {
      return this.#model.scope.membersOf(this.#model, {
        tags: [import_common.ElementTag.Command],
        conformance: "conformant"
      });
    }
    /**
     * The cluster's conformant events.
     */
    get events() {
      return this.#model.scope.membersOf(this.#model, {
        tags: [import_common.ElementTag.Event],
        conformance: "conformant"
      });
    }
  }
  ClusterModel2.Conformant = Conformant;
})(ClusterModel || (ClusterModel = {}));
//# sourceMappingURL=ClusterModel.js.map
