{% import "macros/icons.html" as icons %}

{% macro form_field_label(field) %}
<label class="block text-sm font-medium mb-1" for="{{ field.id }}">
  {{ _(field.label) }}
  {% if field.flags.required %}
    <span class="text-rose-500">*</span>
  {% endif %}
</label>
{% endmacro %}

{% macro form_field_errors(field) %}
  {% if field.errors %}
      {% for error in field.errors %}
        <div class="text-xs mt-1 text-red-500" data-form-error>{{ error | e }}</div>
      {% endfor %}
    {% endif %}
{% endmacro %}

{% macro form_field_description(field) %}
  {% if field.description %}
    <div class="text-justify text-xs mt-1">{{ field.description }}</div>
  {% endif %}
{% endmacro %}

{% macro form_standard_field(field) %}
{{ form_field_label(field) }}
{{ field(class="form-input w-full", **kwargs) }}
{% endmacro %}

{% macro form_checkbox_field(field) %}
<label class="flex items-center text-sm font-medium" for="{{ field.id }}">
  {{ field(class="form-checkbox", **kwargs) }}
  <span class="ml-2">{{ field.label }}</span>
  {% if field.flags.required %}
    <span class="text-rose-500">*</span>
  {% endif %}
</label>
{% endmacro %}

{% macro form_select_field(field) %}
{{ form_field_label(field) }}
{{ field(class="form-select w-full", **kwargs) }}
{% endmacro %}

{% macro form_select_multiple_checkbox_field(field) %}
{{ form_field_label(field) }}
{% for item in field %}
  <div>
    {{ item(class="form-checkbox", **kwargs) }}
    <span class="ml-2">{{ item.label }}</span>
  </div>
{% endfor %}
{% endmacro %}

{% macro form_combobox_select_field(field) %}
{{ form_field_label(field) }}
{{ field(id=field.id ~ "hidden") }}
<div class="flex">
  <input
    id="{{ field.id }}"
    type="text"
    class="form-select w-full pr-9"
    name="{{ field.query_parameter_name }}"
    hx-get="{{ field.query_endpoint_path }}"
    hx-trigger="keyup,focus"
    hx-target="#{{ field.id }}-combobox-results"
    hx-headers='{"HX-Combobox": true}'
    autocomplete="off"
    value="{{ field.data[field.label_attr] }}"
  />
  {% if not field.flags.required %}
    <button
      type="button"
      _="
        init
          set :inputElement to previous <input[type='hidden'] /> from me
          set :queryElement to previous <input /> from me
        end
        on click
          set :inputElement.value to ''
          set :queryElement.value to ''
        end
      "
    >
      {{ icons.x_mark("w-4 h-4 fill-current text-slate-400 group-hover:text-slate-500 ml-2") }}
    </button>
  {% endif %}
</div>
<div class="relative">
  <div
    id="{{ field.id }}-combobox-results"
    class="absolute w-full bg-white focus:outline-none mt-1 transition ease-out duration-200 transform"
    _="
      init
        set :inputElement to previous <input[type='hidden'] /> from me
        set :queryElement to previous <input /> from me
        hide me
      end
      on click in closest <ul > li />
        set :inputElement.value to target@data-value
        set :queryElement.value to target@data-label
        hide me
      end
      on keyup or focus from previous <input /> from me
        show me
      end
      on click from the document
        if target is not me and target is not in me and target is not :queryElement
          hide me
        end
      end
    "
  ></div>
</div>
{% endmacro %}

{% macro form_combobox_select_multiple_field_item(value, label) %}
<li class="flex" data-value="{{ value }}">
  <label class="grow block text-sm mb-1">{{ label }}</label>
  <button
    type="button"
    class="ml-2"
    _="
      on click
        set itemElement to closest <li />
        remove <option[value=`${itemElement@data-value}`] /> from previous <select /> from me
        remove itemElement
      end
    "
  >
    {{ icons.trash('w-4 h-4') }}
  </button>
</li>
{% endmacro %}

{% macro form_combobox_select_multiple_field(field) %}
{{ form_field_label(field) }}
{{ field(id=field.id ~ "hidden", class="hidden") }}
<template>
  {{ form_combobox_select_multiple_field_item('', '') }}
</template>
<ul class="mb-2">
  {% for item in field.data or [] %}
    {{ form_combobox_select_multiple_field_item(item[field.value_attr], item[field.label_attr]) }}
  {% endfor %}
</ul>
<input
  id="{{ field.id }}"
  type="text"
  class="form-select w-full"
  name="{{ field.query_parameter_name }}"
  hx-get="{{ field.query_endpoint_path }}"
  hx-trigger="keyup,focus"
  hx-target="#{{ field.id }}-combobox-results"
  hx-headers='{"HX-Combobox": true}'
  autocomplete="off"
/>
<div class="relative">
  <div
    id="{{ field.id }}-combobox-results"
    class="absolute w-full bg-white focus:outline-none mt-1 transition ease-out duration-200 transform"
    _="
      init
        set :inputElement to previous <select /> from me
        set :selectedListElement to previous <ul /> from me
        set :queryElement to previous <input /> from me
        hide me
      end
      on click in closest <ul > li />
        set selectedOption to <option[value=`${target@data-value}`] /> in :inputElement
        if no selectedOption
          append `<option value='${target@data-value}' selected>${target@data-label}</option>` to :inputElement

          set itemTemplate to previous <template />
          call itemTemplate.content.firstElementChild.cloneNode(true)
          put target@data-label into first <label /> in it
          set it@data-value to target@data-value
          put it at the end of :selectedListElement

          set :queryElement.value to ''
        end
      end
      on keyup or focus from previous <input /> from me
        show me
      end
      on click from the document
        if target is not me and target is not in me and target is not :queryElement
          hide me
        end
      end
    "
  ></div>
</div>
{% endmacro %}

{% macro form_combobox_select_field_results(results, value_attr, label_attr, no_result_label) %}
<ul class="divide-y divide-gray-100 rounded shadow-lg p-2 ring-1 ring-black ring-opacity-5">
  {% for result in results %}
    <li
      class="w-full rounded text-sm hover:bg-slate-100 py-1 px-3 cursor-pointer"
      data-value="{{ result[value_attr] }}"
      data-label="{{ result[label_attr] }}"
    >
      {{ caller(result) }}
    </li>
  {% endfor %}
  {% if results | length == 0 %}
    <li
      class="w-full rounded text-sm hover:bg-slate-100 py-1 px-3 text-primary-500 pointer-events-none"
    >
      {{ no_result_label }}
    </li>
  {% endif %}
</ul>
{% endmacro %}

{% macro form_address_field(field) %}
<div class="space-y-2">
  {{ form_field_label(field) }}
  {{ form_field(field.line1) }}
  {{ form_field(field.line2) }}
  <div class="grid grid-cols-2 gap-2">
    {{ form_field(field.postal_code) }}
    {{ form_field(field.city) }}
  </div>
  {{ form_field(field.state) }}
  {{ form_select_field(field.country) }}
</div>
{% endmacro %}

{% macro form_field_list_item(item) %}
<div class="flex gap-2 mb-2 item-group">
  {% if item is iterable %}
    {% for sub_field in item %}
      <div class="grow">
        {{ sub_field(class="form-input w-full", **kwargs) }}
        {{ form_field_errors(sub_field) }}
      </div>
    {% endfor %}
  {% else %}
    <div class="grow">
      {{ item(class="form-input w-full", **kwargs) }}
      {{ form_field_errors(item) }}
    </div>
  {% endif %}
  <button
    type="button"
    class="ml-2"
    _="on click remove closest <div />"
  >
    {{ icons.trash('w-4 h-4') }}
  </button>
</div>
{% endmacro %}

{% macro form_field_list(field) %}
{{ form_field_label(field) }}
{% for item in field %}
  {{ form_field_list_item(item, **kwargs) }}
{% endfor %}
<template>
  {%
    set field_template = field.append_entry()
  %}
  {{ form_field_list_item(field_template, value='', **kwargs) }}
</template>
<button
  type="button"
  class="btn-xs bg-white border-slate-200 hover:border-slate-300 text-slate-600"
  _="
    on click
      set itemTemplate to previous <template />
      call itemTemplate.content.firstElementChild.cloneNode(true)
      put it before me
      htmx.process(it)
      for itemGroup in <div .item-group /> in closest <div /> index i
        for input in <input /> in itemGroup
          set input_id to input@id
          js(input_id, i)
            return input_id.replace(/\d+/, i)
          end
          set input@id to it
          set input@name to it
        end
      end
    end
  "
>
  Add
</button>
{% endmacro %}

{% macro form_field(field, class) %}
<div class="{{ class }}">
  {% if field.type == "BooleanField" %}
    {{ form_checkbox_field(field, **kwargs) }}
    {{ form_field_errors(field) }}
  {% elif field.type == "SelectField" %}
    {{ form_select_field(field, **kwargs) }}
    {{ form_field_errors(field) }}
  {% elif field.type == "SelectMultipleFieldCheckbox" %}
    {{ form_select_multiple_checkbox_field(field, **kwargs) }}
    {{ form_field_errors(field) }}
  {% elif field.type == "ComboboxSelectField" %}
    {{ form_combobox_select_field(field, **kwargs) }}
    {{ form_field_errors(field) }}
  {% elif field.type == "ComboboxSelectMultipleField" %}
    {{ form_combobox_select_multiple_field(field, **kwargs) }}
    {{ form_field_errors(field) }}
  {% elif field.type == "AddressFormField" %}
    {{ form_address_field(field, **kwargs) }}
  {% elif field.type == "FieldList" %}
    {{ form_field_list(field, **kwargs) }}
  {% else %}
    {{ form_standard_field(field, **kwargs) }}
    {{ form_field_errors(field) }}
  {% endif %}
  {{ form_field_description(field) }}
</div>
{% endmacro %}

{% macro form_csrf_token(form) %}
  {% if form.csrf_token %}
    {{ form.csrf_token }}
    {{ form_field_errors(form.csrf_token) }}
  {% endif %}
{% endmacro %}
