/**
 * @license
 * Copyright 2022-2026 Matter.js Authors
 * SPDX-License-Identifier: Apache-2.0
 */
import { Conformance, DataModelPath, SchemaImplementationError } from "@matter/model";
class UnsupportedConformanceNodeError extends SchemaImplementationError {
  constructor(schema, compiledNode) {
    super(
      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 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 = {
  [Conformance.Operator.EQ]: (a, b) => a === b,
  [Conformance.Operator.GT]: (a, b) => a > b,
  [Conformance.Operator.GTE]: (a, b) => a >= b,
  [Conformance.Operator.LT]: (a, b) => a < b,
  [Conformance.Operator.LTE]: (a, b) => a <= b
};
function performComparison(operatorName, lhs, rhs, schema, location) {
  const operator = ComparisonOperators[operatorName];
  if (operator === void 0) {
    throw new SchemaImplementationError(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, 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);
    }
  };
}
export {
  Code,
  ConformantNode,
  NonconformantNode,
  UnsupportedConformanceNodeError,
  asBoolean,
  asConformance,
  assertValue,
  createBooleanTest,
  createComparison,
  createLogicalBinaryEvaluator,
  createLogicalInversion,
  evaluateNode,
  isStatic
};
//# sourceMappingURL=conformance-util.js.map
