/**
 * @license
 * Copyright 2022-2026 Matter.js Authors
 * SPDX-License-Identifier: Apache-2.0
 */
import { Aspect } from "./Aspect.js";
class Quality extends Aspect {
  /**
   * The value may be null.
   */
  nullable;
  /**
   * An attribute persists across restarts.
   *
   * Note that Matter designates any configuration as persistent so matter.js persists writable attributes even
   * without this flag.
   */
  nonvolatile;
  /**
   * An attribute never changes unless software revision changes.
   */
  fixed;
  /**
   * An attribute changes rapidly so subscriptions would not be useful.  Not available for subscription.
   */
  changesOmitted;
  /**
   * An attribute contributes to a scene.
   */
  scene;
  /**
   * An attribute generates data useful for interval or change reporting.
   */
  reportable;
  /**
   * A cluster only appears once on a node for a given device type.
   */
  singleton;
  /**
   * An attribute or event broadcasts a limited number of occurrences for performance reasons.
   */
  quieter;
  /**
   * A command's input or output may be larger than than an IPv6 MTU of 1280 bytes.
   */
  largeMessage;
  /**
   * A cluster provides verbose diagnostics and will be omitted from wildcard expansion.
   */
  diagnostics;
  /**
   * Writes to an attribute are legal only in the context of a transaction.
   */
  atomic;
  /**
   * A set of properties disallowed for a device type.
   */
  disallowed;
  /**
   * Initialize from a Quality.All definition or a string conforming to the
   * "other quality" DSL defined in the Matter specification.
   */
  constructor(definition) {
    super(definition);
    let ast;
    if (typeof definition === "string") {
      ast = {};
      this.#parse(ast, definition);
    } else if (Array.isArray(definition)) {
      ast = {};
      definition.map((f) => this.#parse(this, f));
    } else {
      ast = definition;
    }
    this.nullable = ast?.nullable;
    this.nonvolatile = ast?.nonvolatile;
    this.fixed = ast?.fixed;
    this.changesOmitted = ast?.changesOmitted;
    this.scene = ast?.scene;
    this.reportable = ast?.reportable;
    this.singleton = ast?.singleton;
    this.quieter = ast?.quieter;
    this.largeMessage = ast?.largeMessage;
    this.diagnostics = ast?.diagnostics;
    this.atomic = ast?.atomic;
    this.disallowed = ast?.disallowed;
    this.isEmpty = !(this.nullable || this.nonvolatile || this.fixed || this.changesOmitted || this.scene || this.reportable || this.singleton || this.quieter || this.largeMessage || this.diagnostics || this.atomic);
    this.freeze();
  }
  extend(other) {
    if (other.isEmpty) {
      return this;
    }
    if (this.isEmpty) {
      return other;
    }
    return new Quality({
      nullable: other.nullable ?? this.nullable,
      nonvolatile: other.nonvolatile ?? this.nonvolatile,
      fixed: other.fixed ?? this.fixed,
      changesOmitted: other.changesOmitted ?? this.changesOmitted,
      scene: other.scene ?? this.scene,
      reportable: other.reportable ?? this.reportable,
      singleton: other.singleton ?? this.singleton,
      quieter: other.quieter ?? this.quieter,
      largeMessage: other.largeMessage ?? this.largeMessage,
      diagnostics: other.diagnostics ?? this.diagnostics,
      disallowed: other.disallowed ?? this.disallowed
    });
  }
  #parse(ast, definition) {
    const text = definition.toUpperCase();
    if (text === "DERIVED") {
      return;
    }
    let disallow = false;
    for (const char of text) {
      if (char === " " || char === "	") {
        continue;
      }
      if (char === "!") {
        disallow = true;
        continue;
      }
      const field = Quality.Flag[char];
      if (field) {
        if (ast.disallowed?.[field]) {
          continue;
        }
        if (disallow) {
          delete ast[field];
          if (!ast.disallowed) {
            ast.disallowed = {};
          }
          ast.disallowed[field] = true;
          disallow = false;
        } else {
          ast[field] = true;
        }
      } else {
        this.error("UNKNOWN_QUALITY_FLAG", `Unknown flag "${char}"`);
      }
    }
  }
  /**
   * Display quality using standard Matter syntax.
   */
  toString() {
    const flags = [];
    for (const f of Quality.FlagNames) {
      const field = Quality.Flag[f];
      if (this[field] && !this.disallowed?.[field]) {
        flags.push(f);
      }
    }
    return flags.join(" ");
  }
}
((Quality2) => {
  let Field;
  ((Field2) => {
    Field2["nullable"] = "X";
    Field2["nonvolatile"] = "N";
    Field2["fixed"] = "F";
    Field2["scene"] = "S";
    Field2["reportable"] = "P";
    Field2["changesOmitted"] = "C";
    Field2["singleton"] = "I";
    Field2["quieter"] = "Q";
    Field2["largeMessage"] = "L";
    Field2["diagnostics"] = "K";
    Field2["atomic"] = "T";
  })(Field = Quality2.Field || (Quality2.Field = {}));
  let Flag;
  ((Flag2) => {
    Flag2["X"] = "nullable";
    Flag2["N"] = "nonvolatile";
    Flag2["F"] = "fixed";
    Flag2["S"] = "scene";
    Flag2["P"] = "reportable";
    Flag2["C"] = "changesOmitted";
    Flag2["I"] = "singleton";
    Flag2["Q"] = "quieter";
    Flag2["L"] = "largeMessage";
    Flag2["K"] = "diagnostics";
    Flag2["T"] = "atomic";
  })(Flag = Quality2.Flag || (Quality2.Flag = {}));
  Quality2.FlagNames = ["X", "N", "F", "S", "P", "C", "I", "Q", "L", "K", "T"];
})(Quality || (Quality = {}));
export {
  Quality
};
//# sourceMappingURL=Quality.js.map
