# Array validators for {{ feature_name }}
#
# Validators for repeating groups and array constraints.

let common = import "./common.ncl" in
let constraints = import "../constraints.toml" in

{
{% for array_field in array_fields %}
  # Uniqueness validator for {{ array_field.name }}
  Unique{{ array_field.name | capitalize }} = fun label =>
    std.contract.from_predicate (fun arr =>
      std.is_array arr &&
      let values = std.array.map (fun item => item.{{ array_field.unique_key }}) arr in
      let sorted = std.array.sort values in
      let unique_count = std.array.fold_left
        (fun acc => fun val =>
          if acc.prev == val then
            acc
          else
            {count = acc.count + 1, prev = val}
        )
        {count = 0, prev = null}
        sorted
      in
      unique_count.count == std.array.length arr
    ) {
      label = label,
      message = "{{ array_field.name }} items must have unique {{ array_field.unique_key }} values",
    },

  # Length validator for {{ array_field.name }}
  Valid{{ array_field.name | capitalize }}Length = fun label =>
    std.contract.from_predicate (fun arr =>
      std.is_array arr &&
      let len = std.array.length arr in
      {% if array_field.min_items %}len >= {{ array_field.min_items }} &&{% endif %}
      {% if array_field.max_items %}len <= {{ array_field.max_items }} &&{% endif %}
      true
    ) {
      label = label,
      message = "{{ array_field.name }} array length must be between {{ array_field.min_items | default(value="0") }} and {{ array_field.max_items | default(value="unlimited") }}",
    },

  # Composite validator for {{ array_field.name }}
  Valid{{ array_field.name | capitalize }}Full = fun label =>
    fun value =>
      value
      | Valid{{ array_field.name | capitalize }}Length label
      {% if array_field.unique %}| Unique{{ array_field.name | capitalize }} label{% endif %}
      ,

{% endfor %}
  # Master array validation
  validate_arrays = fun config => {
{% for array_field in array_fields %}
    {{ array_field.name }} = config.{{ array_field.name }} | Valid{{ array_field.name | capitalize }}Full "{{ feature_name }}.{{ array_field.name }}",
{% endfor %}
    ..config
  },
}
