"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 constraint_exports = {};
__export(constraint_exports, {
  createConstraintValidator: () => createConstraintValidator
});
module.exports = __toCommonJS(constraint_exports);
var import_general = require("@matter/general");
var import_model = require("@matter/model");
var import_protocol = require("@matter/protocol");
var import_NameResolver = require("../managed/NameResolver.js");
var import_assertions = require("./assertions.js");
/**
 * @license
 * Copyright 2022-2026 Matter.js Authors
 * SPDX-License-Identifier: Apache-2.0
 */
function createConstraintValidator(constraint, schema, supervisor) {
  let nameResolvers;
  const nameResolverFactory = (location) => {
    return (name) => {
      if (nameResolvers === void 0) {
        nameResolvers = {};
      }
      if (name in nameResolvers) {
        return nameResolvers[name]?.(location.siblings) ?? location.outerResolve?.(name);
      }
      const resolver = (0, import_NameResolver.NameResolver)(supervisor, schema.parent, name);
      nameResolvers[name] = resolver;
      return resolver?.(location.siblings) ?? location.outerResolve?.(name);
    };
  };
  const inner = create(constraint, schema, nameResolverFactory);
  if (!inner) {
    return void 0;
  }
  return (value, session, location) => {
    const cfg = location.config?.supervision;
    if (cfg?.validate === false || cfg?.constraint === false) {
      return;
    }
    inner(value, session, location);
  };
}
function create(constraint, schema, nameResolverFactory) {
  if (constraint.isEmpty) {
    return;
  }
  const metatype = schema.effectiveMetatype;
  if (metatype === import_model.Metatype.array) {
    return createArrayConstraintValidator(constraint, schema, nameResolverFactory);
  }
  if (constraint.in) {
    return (value, _session, location) => {
      if (!constraint.test(value, nameResolverFactory(location))) {
        throw new import_protocol.ConstraintError(
          schema,
          location,
          `Value ${value} is not one of the values allowed by "in" constraint`
        );
      }
    };
  }
  switch (schema.effectiveMetatype) {
    case import_model.Metatype.integer:
    case import_model.Metatype.float:
      return (value, _session, location) => {
        (0, import_assertions.assertNumeric)(value, location);
        if (!constraint.test(value, nameResolverFactory(location))) {
          throw new import_protocol.ConstraintError(
            schema,
            location,
            `Value ${value} is not within bounds defined by constraint`
          );
        }
      };
    case import_model.Metatype.boolean:
      return (value, _session, location) => {
        (0, import_assertions.assertBoolean)(value, location);
        if (!constraint.test(value, nameResolverFactory(location))) {
          throw new import_protocol.ConstraintError(schema, location, `Value ${value} is disallowed by constraint`);
        }
      };
    case import_model.Metatype.string: {
      const validateLength = (value, _session, location) => {
        (0, import_assertions.assertSequence)(value, location);
        const length = typeof value === "string" ? value.length : value.byteLength;
        if (!constraint.test(length, nameResolverFactory(location))) {
          throw new import_protocol.ConstraintError(
            schema,
            location,
            `String length of ${length} is not within bounds defined by constraint`
          );
        }
      };
      const { cpMax } = constraint;
      if (cpMax === void 0) {
        return validateLength;
      }
      return (value, _session, location) => {
        validateLength(value, _session, location);
        (0, import_assertions.assertString)(value, location);
        const codepointCount = [...value].length;
        if (codepointCount > cpMax) {
          throw new import_protocol.ConstraintError(
            schema,
            location,
            `Codepoint count of ${codepointCount} is not within bounds defined by constraint`
          );
        }
      };
    }
    case import_model.Metatype.bytes:
      return (value, _session, location) => {
        (0, import_assertions.assertSequence)(value, location);
        const length = typeof value === "string" ? value.length : value.byteLength;
        if (!constraint.test(length, nameResolverFactory(location))) {
          throw new import_protocol.ConstraintError(
            schema,
            location,
            `Byte length of ${length} is not within bounds defined by constraint`
          );
        }
      };
    default:
      throw new import_general.InternalError(`Cannot define constraint for unsupported metatype ${schema.effectiveMetatype}`);
  }
}
function createArrayConstraintValidator(constraint, schema, nameResolver) {
  let validateEntryConstraint;
  if (constraint.entry) {
    const entrySchema = schema.listEntry;
    if (entrySchema) {
      validateEntryConstraint = create(constraint.entry, entrySchema, nameResolver);
    }
  }
  return (value, session, location) => {
    (0, import_assertions.assertArray)(value, location);
    if (!constraint.test(value.length, nameResolver(location))) {
      throw new import_protocol.ConstraintError(
        schema,
        location,
        `Array length ${value.length} is not within bounds defined by constraint`
      );
    }
    if (validateEntryConstraint) {
      const sublocation = {
        ...location,
        path: location.path.at("")
      };
      let pos = 0;
      for (const e of value) {
        if (e === void 0 || e === null) {
          continue;
        }
        sublocation.path.id = pos;
        validateEntryConstraint(e, session, sublocation);
        pos++;
      }
    }
  };
}
//# sourceMappingURL=constraint.js.map
