{# Macros for form and form field rendering.

Connects WTForms, Fomantic-UI and HTMX.
#}
{% macro render_input(
field,
label_visible=true,
icon=none,
container=true,
noindicator=false,
indicator_icon=none,
indicator_text=none,
display=true,
add_button=false,
del_button=false
) -%}
{%- set field_visible = field.type != 'HiddenField' and field.type !='CSRFTokenField' -%}
{%- set disabled = kwargs.get("disabled") or (field.render_kw and "disabled" in field.render_kw) -%}
{%- set readonly = kwargs.get("readonly") or (field.render_kw and "readonly" in field.render_kw) -%}
{%- set required = "required" in field.flags -%}
{%- set lock_indicator = readonly or disabled -%}
{%- set corner_indicator = not noindicator and (indicator_icon or lock_indicator or required) -%}
{%- set inline_validation = field.validators and field.type not in ("FileField", "MultipleFileField") -%}
{%- if inline_validation -%}
    {%- set ignore_me = kwargs.update({"hx-post": ""}) -%}
    {%- set ignore_me = kwargs.update({"hx-indicator": "closest .input", "hx-trigger": "input changed delay:500ms"}) -%}
{%- endif -%}
{%- if request.headers.get("HX-Request") and not request.headers.get("HX-Boosted") -%}
    {# Prevent password to be automatically refilled when reset during edition #}
    {%- if field.type == "PasswordField" -%}
        {%- set ignore_me = kwargs.update({"autocomplete": "new-password"}) -%}
    {%- else -%}
        {%- set ignore_me = kwargs.update({"autocomplete": "off"}) -%}
    {%- endif -%}
{%- endif -%}

{% if container and field_visible -%}
    {# open field container #}
    <div class="field {{ kwargs.pop('class_', '') }}
                {%- if field.errors %} error{% endif -%}
                {%- if disabled %} disabled{% endif -%}
                {%- if not display %} hidden{% endif -%}"

         {% if inline_validation %}hx-target="this" hx-swap="morph"{% endif %}
    >
{% endif -%}

{%- if field_visible and label_visible -%}
    {{ field.label() }}
{%- endif -%}

{%- if field_visible -%}
    {# open action container #}
    {% if add_button or del_button %}
        <div class="ui action input">
    {% endif %}

    {# input container #}
    <div class="ui
                {%- if corner_indicator %} corner labeled{% endif -%}
                {%- if icon or field.description %} left icon{% endif -%}
                {%- if field_visible and ((add_button or del_button) and not readonly and not disabled) or caller is defined %} action{% endif -%}
                {%- if field.type not in ("BooleanField", "RadioField") %} input{% endif -%}
               ">
{% endif %}
{% if icon %}<i class="{{ icon }} icon"></i>{% endif %}
{% if field.description %}<i class="question circle link icon" title="{{ field.description }}"></i>{% endif %}

{% if field.type not in ("SelectField", "SelectMultipleField") %}
    {{ field(**kwargs) }}
{% elif field.type == "SelectMultipleField" and readonly %}
    {{ field(class_="ui fluid dropdown multiple read-only", **kwargs) }}
{% elif field.type == "SelectMultipleField" %}
    {{ field(class_="ui fluid dropdown multiple", **kwargs) }}
{% elif field.type == "SelectField" and readonly %}
    {{ field(class_="ui fluid dropdown read-only", **kwargs) }}
{% elif field.type == "SelectField" %}
    {{ field(class_="ui fluid dropdown", **kwargs) }}
{% endif %}

{% if not noindicator %}
    {% if indicator_icon %}
        <div class="ui corner label"{% if indicator_text %} title="{{ indicator_text }}"{% endif %}>
            <i class="{{ indicator_icon }} icon"></i>
        </div>
    {% elif lock_indicator %}
        <div class="ui corner label" title="{{ _("This field is not editable") }}">
            <i class="lock icon"></i>
        </div>
    {% elif required %}
        <div class="ui corner label" title="{{ _("This field is required") }}">
            <i class="asterisk icon"></i>
        </div>
    {% endif %}
{% endif %}

{% if field_visible %}
    {# close input container #}
    </div>

    {% if caller is defined %}
        {{ caller() }}
    {% else %}
        {% if del_button %}
            <button
                class="ui teal icon button"
                title="{{ _("Remove this field") }}"
                type="submit"
                name="fieldlist_remove"
                value="{{ field.name }}"
                hx-target="closest .fieldlist"
                formnovalidate>
                <i class="minus icon"></i>
            </button>
        {% endif %}
        {% if add_button and not readonly and not disabled %}
            <button
                class="ui teal icon button"
                title="{{ _("Add another field") }}"
                type="submit"
                name="fieldlist_add"
                value="{{ field.name }}"
                hx-target="closest .fieldlist"
                formnovalidate>
                <i class="plus icon"></i>
            </button>
        {% endif %}

        {# close action container #}
        {% if add_button or del_button %}
            </div>
        {% endif %}
    {% endif %}
{% endif %}

{% if field.errors %}
    {% for error in field.errors %}
        <div class="ui pointing red basic label">
            <p>{{ error }}</p>
        </div>
    {% endfor %}
{% endif %}

{% set display_strength_indicator = field.render_kw and "class" in field.render_kw and "password_strength" in field.render_kw["class"] %}
{% set strength = field.data|password_strength %}
{% if display_strength_indicator and strength and not field.errors %}
    <div>
        <p class="progress_bar">{% trans %}Password strength{% endtrans %}</p>
        <div class="ui indicating progress" data-percent="{{ strength }}">
            <div class="bar strength{{ strength }}">
            </div>
        </div>
    </div>
{% endif %}

{% if container and field_visible %}
    {# close field container #}
    </div>
{% endif %}

{%- endmacro %}

{% macro render_fields(form) %}
    {% for field in form %}
        {{ render_field(field) }}
    {% endfor %}
{% endmacro %}

{% macro render_field(field, parent_list=none, parent_indice=none) -%}
    {% if parent_list %}
        {% set last = parent_indice >= parent_list.entries|len -1 %}
        {% set ignore_me = kwargs.update({
        "label_visible": false,
        "add_button": (last and (not parent_list.max_entries or parent_indice < parent_list.max_entries)),
        "del_button": (last and parent_list.min_entries and parent_indice >= parent_list.min_entries),
        }) %}
    {% endif %}
    {% if field.type == "FieldList" %}
        {{ render_list(field, **kwargs) }}
    {% elif field.type == "BooleanField" %}
        {{ render_checkbox(field, **kwargs) }}
    {% else %}
        {{ render_input(field, **kwargs) }}
    {% endif %}
{%- endmacro %}

{% macro render_list(field, render_func=none) -%}
    <div class="field fieldlist" id="{{ field.name }}">
        {# Strangely enough, translations are not rendered when using field.label() #}
        {{ field[0].label() }}
        {% for subfield in field %}
            {% set ignore_me = kwargs.update(**field.render_kw or {}) %}
            {{ (render_func or render_field)(
            subfield,
            parent_list=field,
            parent_indice=loop.index0,
            **kwargs
            ) }}
        {% endfor %}
    </div>
{%- endmacro %}

{% macro render_checkbox(field, display=true, label_visible=true) -%}
    <div class="field{% if not display %} hidden{% endif %}">
        <div class="ui toggle checkbox {{ kwargs.pop('class_', '') }}">
            {{ field(**kwargs) }}
            {% if label_visible %}{{ field.label() }}{% endif %}
        </div>
    </div>
{%- endmacro %}

{% macro render_form(
form,
action_text=none,
class_='',
btn_class='ui right floated primary button',
action=none,
id=none,
csrf=true) -%}
<form method="POST"
      id="{{ id or form.__class__.__name__|lower }}"
      action="{% if action %}{{ action }}{% elif form.action is defined %}{{ form.action }}{% endif %}"
      role="form"
      enctype="multipart/form-data"
      class="ui initial form {{ class_ }}"
      {% for key, value in kwargs.items() %}{{ key.replace("_", "-") }}="{{ value }}" {% endfor %}
>
    {% if caller is defined %}
        {% if csrf %}
            <input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
        {% endif %}
        {{ caller() }}
    {% else %}
        {{ render_fields(form) }}
    {% endif %}
    {% if action_text %}
        <div class="ui right aligned container">
            <div class="ui stackable buttons">
                <button type="submit" class="{{ btn_class }}">{{ action_text }}</button>
            </div>
        </div>
    {% endif %}
</form>
{%- endmacro %}
