"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 InferredComponents_exports = {};
__export(InferredComponents_exports, {
  InferredComponents: () => InferredComponents
});
module.exports = __toCommonJS(InferredComponents_exports);
var import_general = require("@matter/general");
var import_models = require("../../models/index.js");
/**
 * @license
 * Copyright 2022-2026 Matter.js Authors
 * SPDX-License-Identifier: Apache-2.0
 */
function InferredComponents(cluster) {
  const result = [];
  cluster.allAces.forEach((child) => addElement(result, child));
  return result;
}
function pattern(...parts) {
  parts = parts.map((p) => {
    switch (p) {
      case "[":
      case "]":
      case "(":
      case ")":
        return `\\${p}`;
      default:
        return p;
    }
  });
  return new RegExp(`^${parts.join("")}$`);
}
const FEATURE_NAME = "[A-Z_][A-Z_0-9]+";
const FEATURE = `(${FEATURE_NAME})`;
const CONJUNCT_FEATURES = `(${FEATURE_NAME}(?: & ${FEATURE_NAME})*)`;
const DISJUNCT_FEATURES = CONJUNCT_FEATURES.replace(/&/g, "[|,]");
const FIELD = "[A-Z][A-Za-z_$]*[a-z][A-Za-z_$]*";
const CONJUNCT_FIELDS = `(${FIELD}(?: & ${FIELD})*)`;
const DISJUNCT_FIELDS = CONJUNCT_FIELDS.replace(/&/g, "[|,]");
const AND = " & ";
const NOT = "!";
function splitConjunction(conjunction) {
  return conjunction.split(" & ");
}
function splitDisjunction(disjunction) {
  return disjunction.split(" | ");
}
const VarianceMatchers = [
  // Mandatory, unconditional
  {
    pattern: pattern("(?:|M)"),
    processor(add) {
      add();
    }
  },
  // Optional, unconditional
  {
    pattern: pattern("(?:O|desc)"),
    processor(add) {
      add(true);
    }
  },
  // fieldName (optional, unconditional).  Ignores field reference which can only be enforced at runtime
  {
    pattern: pattern(FIELD),
    processor(add) {
      add(true);
    }
  },
  // [fieldName] (optional, unconditional).  Ignores field reference which can only be enforced at runtime
  {
    pattern: pattern("[", FIELD, "]"),
    processor(add) {
      add(true);
    }
  },
  // fieldName > num (optional, unconditional).  Ignores field expression
  {
    pattern: pattern(FIELD, " > ", "\\d+"),
    processor(add) {
      add(true);
    }
  },
  // fieldName, O (optional, unconditional).  Ignores field reference
  {
    pattern: pattern(FIELD, ", ", "O"),
    processor(add) {
      add(true);
    }
  },
  // FOO & fieldName (field ignored as must be runtime enforced)
  {
    pattern: pattern(FEATURE, AND, FIELD),
    processor(add, match) {
      add(true, { allOf: match });
    }
  },
  // FOO<& BAR>*
  {
    pattern: pattern(CONJUNCT_FEATURES),
    processor(add, match) {
      add(false, { allOf: splitConjunction(match[0]) });
    }
  },
  // [FOO<& BAR>*]
  {
    pattern: pattern("[", CONJUNCT_FEATURES, "]"),
    processor(add, match) {
      add(true, { allOf: splitConjunction(match[0]) });
    }
  },
  // [FOO<| BAR>+]
  {
    pattern: pattern("[", DISJUNCT_FEATURES, "]"),
    processor(add, match) {
      add(true, { anyOf: splitDisjunction(match[0]) });
    }
  },
  // FOO<| BAR>* or FOO<, BAR>*
  {
    pattern: pattern(DISJUNCT_FEATURES),
    processor(add, match) {
      add(false, { anyOf: splitDisjunction(match[0]) });
    }
  },
  // Field<| Field>* or Field<, Field>* (optional, unconditional).  Ignores field references
  {
    pattern: pattern(DISJUNCT_FIELDS),
    processor(add) {
      add(true);
    }
  },
  // [Field<| Field>*] or [Field<, Field>*] (optional, unconditional.  Ignores field references)
  {
    pattern: pattern("[", DISJUNCT_FIELDS, "]"),
    processor(add) {
      add(true);
    }
  },
  // FOO, [BAR]
  {
    pattern: pattern(FEATURE, ", ", "[", FEATURE, "]"),
    processor(add, match) {
      add(false, { allOf: [match[0]] });
      add(true, { allOf: [match[1]] });
    }
  },
  // FOO & !BAR
  {
    pattern: pattern(FEATURE, AND, NOT, FEATURE),
    processor(add, match) {
      add(false, { allOf: [match[0]], not: match[1] });
    }
  },
  // !FOO & BAR
  {
    pattern: pattern(NOT, FEATURE, AND, FEATURE),
    processor(add, match) {
      add(false, { allOf: [match[1]], not: match[0] });
    }
  },
  // !FOO & [BAR]
  {
    pattern: pattern(NOT, FEATURE, AND, "[", FEATURE, "]"),
    processor(add, match) {
      add(true, { allOf: [match[1]], not: match[0] });
    }
  },
  // !FOO & (BAR<| BIZ>*)
  {
    pattern: pattern(NOT, FEATURE, AND, "(", DISJUNCT_FEATURES, ")"),
    processor(add, match) {
      add(true, { allOf: splitDisjunction(match[1]), not: match[0] });
    }
  },
  // !FOO
  {
    pattern: pattern(NOT, FEATURE),
    processor(add, match) {
      add(false, { not: match[0] });
    }
  },
  // [!FOO]
  {
    pattern: pattern("[", NOT, FEATURE, "]"),
    processor(add, match) {
      add(true, { not: match[0] });
    }
  },
  // [!FOO & BAR]
  {
    pattern: pattern("[", NOT, FEATURE, AND, FEATURE, "]"),
    processor(add, match) {
      add(true, { not: match[0], allOf: [match[1]] });
    }
  },
  // FOO & BAR, [BIZ]
  {
    pattern: pattern(FEATURE, AND, FEATURE, ", ", "[", FEATURE, "]"),
    processor(add, match) {
      add(false, { allOf: match.slice(0, 2) });
      add(true, { allOf: [match[2]] });
    }
  },
  // FOO, O
  {
    pattern: pattern(FEATURE, ", ", "O"),
    processor(add, match) {
      add(false, { allOf: [match[0]] });
      add(true);
    }
  },
  // Handles a bunch of super ugly conformances in deprecated occupancy sensing attributes.  They all effectively
  // become optional if certain features are enabled.  We use the presence of the "HoldTime" field to reliably detect
  // these and ensure these rules aren't too greedy
  {
    pattern: pattern(".*HoldTime", AND, "\\(?", FEATURE, ".*"),
    processor(add, match) {
      add(true, { allOf: [match[0]] });
    }
  }
];
function addElement(components, element) {
  if (import_models.AttributeModel.isGlobal(element)) {
    return;
  }
  let text = element.conformance.toString();
  if (text === "X") {
    return;
  }
  while (true) {
    if (text.match(/^[DP], /)) {
      text = text.substring(3);
    } else {
      break;
    }
  }
  if (text === "D") {
    text = "O";
  } else if (text === "M, D" || text === "P") {
    text = "M";
  }
  for (const matcher of VarianceMatchers) {
    const match = text.match(matcher.pattern);
    if (match) {
      matcher.processor((optional, condition) => {
        addVariance(components, element, optional, condition);
      }, match.slice(1));
      return;
    }
  }
  throw new import_general.NotImplementedError(`New rule needed for conformance "${element.conformance}" (element ${element.path})`);
}
function addVariance(components, element, optional, condition) {
  let into;
  for (const existing of components) {
    if ((0, import_general.isDeepEqual)(existing.condition, condition)) {
      into = existing;
      break;
    }
  }
  if (!into) {
    into = {
      condition,
      optional: [],
      mandatory: []
    };
    if (condition) {
      components.push(into);
    } else {
      components.unshift(into);
    }
  }
  if (optional) {
    into.optional.push(element);
  } else {
    into.mandatory.push(element);
  }
}
//# sourceMappingURL=InferredComponents.js.map
