"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 conformance_util_exports = {};
__export(conformance_util_exports, {
  Code: () => Code,
  ConformantNode: () => ConformantNode,
  NonconformantNode: () => NonconformantNode,
  UnsupportedConformanceNodeError: () => UnsupportedConformanceNodeError,
  asBoolean: () => asBoolean,
  asConformance: () => asConformance,
  assertValue: () => assertValue,
  createBooleanTest: () => createBooleanTest,
  createComparison: () => createComparison,
  createLogicalBinaryEvaluator: () => createLogicalBinaryEvaluator,
  createLogicalInversion: () => createLogicalInversion,
  evaluateNode: () => evaluateNode,
  isStatic: () => isStatic
});
module.exports = __toCommonJS(conformance_util_exports);
var import_model = require("#model");
/**
 * @license
 * Copyright 2022-2026 Matter.js Authors
 * SPDX-License-Identifier: Apache-2.0
 */
class UnsupportedConformanceNodeError extends import_model.SchemaImplementationError {
  constructor(schema, compiledNode) {
    super(
      (0, import_model.DataModelPath)(schema.path),
      `Unknown or unsupported top-level conformance node type ${compiledNode.code}`
    );
  }
}
var Code = /* @__PURE__ */ ((Code2) => {
  Code2["Nonconformant"] = "nonconformant";
  Code2["Conformant"] = "conformant";
  Code2["Optional"] = "optional";
  Code2["Disallowed"] = "disallowed";
  Code2["Value"] = "value";
  Code2["Evaluate"] = "evaluate";
  return Code2;
})(Code || {});
function evaluateNode(node, value, location) {
  if (node.code === "evaluate" /* Evaluate */) {
    return node.evaluate(value, location);
  }
  return node;
}
function asConformance(node) {
  if (node.code === "value" /* Value */) {
    return {
      code: node.value === void 0 ? "nonconformant" /* Nonconformant */ : "conformant" /* Conformant */
    };
  } else {
    return node;
  }
}
function isStatic(node) {
  return node.code !== "evaluate" /* Evaluate */;
}
function asBoolean(node) {
  node = asConformance(node);
  switch (node.code) {
    case "conformant" /* Conformant */:
    case "optional" /* Optional */:
      return true;
    case "value" /* Value */:
      return !!node.value;
    default:
      return false;
  }
}
function assertValue(location, node, where) {
  if (node.code !== "value" /* Value */) {
    throw new import_model.SchemaImplementationError(
      location,
      `Expected a value for ${where} but conformance node is "${node.code}"`
    );
  }
}
const ConformantNode = { code: "conformant" /* Conformant */ };
const NonconformantNode = { code: "nonconformant" /* Nonconformant */ };
function createLogicalInversion(node) {
  const operand = asConformance(node);
  switch (operand.code) {
    case "nonconformant" /* Nonconformant */:
      return ConformantNode;
    case "evaluate" /* Evaluate */:
      const evaluate = operand.evaluate;
      return {
        code: "evaluate" /* Evaluate */,
        evaluate: (value, options) => {
          let staticOperand = evaluate(value, options);
          staticOperand = asConformance(staticOperand);
          if (staticOperand.code === "nonconformant" /* Nonconformant */) {
            return ConformantNode;
          }
          return NonconformantNode;
        }
      };
    default:
      return NonconformantNode;
  }
}
function createLogicalBinaryEvaluator(lhs, rhs, operator) {
  return {
    code: "evaluate" /* Evaluate */,
    evaluate: (value, options) => {
      const staticLhs = evaluateNode(lhs, value, options);
      const staticRhs = evaluateNode(rhs, value, options);
      return operator(asBoolean(staticLhs), asBoolean(staticRhs)) ? ConformantNode : NonconformantNode;
    }
  };
}
const ComparisonOperators = {
  [import_model.Conformance.Operator.EQ]: (a, b) => a === b,
  [import_model.Conformance.Operator.GT]: (a, b) => a > b,
  [import_model.Conformance.Operator.GTE]: (a, b) => a >= b,
  [import_model.Conformance.Operator.LT]: (a, b) => a < b,
  [import_model.Conformance.Operator.LTE]: (a, b) => a <= b
};
function performComparison(operatorName, lhs, rhs, schema, location) {
  const operator = ComparisonOperators[operatorName];
  if (operator === void 0) {
    throw new import_model.SchemaImplementationError((0, import_model.DataModelPath)(schema.path), `Unknown binary operator ${operatorName}`);
  }
  assertValue(location, lhs, `Left-hand side of "${operatorName}"`);
  assertValue(location, rhs, `Right-hand side of "${operatorName}"`);
  if (lhs.value !== void 0 && lhs.value !== null && rhs.value !== void 0 && rhs.value !== null && operator(lhs.value, rhs.value)) {
    return ConformantNode;
  }
  return NonconformantNode;
}
function createComparison(operatorName, lhs, rhs, schema) {
  if (isStatic(lhs) && isStatic(rhs)) {
    return performComparison(operatorName, lhs, rhs, schema, (0, import_model.DataModelPath)(schema.path));
  }
  return {
    code: "evaluate" /* Evaluate */,
    evaluate: (value, location) => performComparison(
      operatorName,
      evaluateNode(lhs, value, location),
      evaluateNode(rhs, value, location),
      schema,
      location
    )
  };
}
function createBooleanTest(node) {
  if (isStatic(node)) {
    return node;
  }
  const { evaluate } = node;
  return {
    code: "evaluate" /* Evaluate */,
    evaluate: (value, location) => {
      const result = evaluate(value, location);
      return asConformance(result);
    }
  };
}
//# sourceMappingURL=conformance-util.js.map
