{#
Creates all the markup required for an input element. Handles matching labels to
inputs, error messages and other useful elements.

name        - The name of the form parameter.
id          - The id to use on the input and label. Convention is to prefix with 'field-'.
label       - The human readable label.
value       - The value of the input.
placeholder - Some placeholder text.
type        - The type of input eg. email, url, date (default: text).
error       - A list of error strings for the field or just true to highlight the field.
classes     - An array of classes to apply to the control-group.
is_required - Boolean of whether this input is requred for the form to validate

Examples:

  {% import 'macros/form.html' as form %}
  {{ form.input('title', label=_('Title'), value=data.title, error=errors.title) }}

#}
{% macro input(name, id='', label='', value='', placeholder='', type='text', error="", classes=[], attrs={}, is_required=false) %}
  {%- set extra_html = caller() if caller -%}

  {% call input_block(id or name, label or name, error, classes, extra_html=extra_html, is_required=is_required) %}
    <input id="{{ id or name }}" type="{{ type }}" name="{{ name }}" value="{{ value | empty_and_escape }}" placeholder="{{ placeholder }}" {{ attributes(attrs) }} />
  {% endcall %}
{% endmacro %}

{#
Builds a single checkbox input.

name        - The name of the form parameter.
id          - The id to use on the input and label. Convention is to prefix with 'field-'.
label       - The human readable label.
value       - The value of the input.
checked     - If true the checkbox will be checked
error       - An error string for the field or just true to highlight the field.
classes     - An array of classes to apply to the control-group.
is_required - Boolean of whether this input is requred for the form to validate

Example:

  {% import 'macros/form.html' as form %}
  {{ form.checkbox('remember', checked=true) }}

#}
{% macro checkbox(name, id='', label='', value='', checked=false, placeholder='', error="", classes=[], attrs={}, is_required=false) %}
  {%- set extra_html = caller() if caller -%}
  <div class="control-group{{ " " ~ classes | join(" ") }}{% if error %} error{% endif %}">
    <div class="controls">
      <label class="checkbox" for="{{ id or name }}">
        <input id="{{ id or name }}" type="checkbox" name="{{ name }}" value="{{ value | empty_and_escape }}" {{ "checked " if checked }} {{ attributes(attrs) }} />
        {{ label or name }}
        {% if is_required %}{{ input_required() }}{% endif %}
        {% if error and error is iterable %}<strong class="error-inline">{{ error|join(', ') }}</strong>{% endif %}
      </label>
      {{ extra_html }}
    </div>
  </div>
{% endmacro %}

{#
Creates all the markup required for an select element. Handles matching labels to
inputs and error messages.

A field should be a dict with a "value" key and an optional "text" key which
will be displayed to the user. We use a dict to easily allow extension in
future should extra options be required.

name        - The name of the form parameter.
id          - The id to use on the input and label. Convention is to prefix with 'field-'.
label       - The human readable label.
options     - A list/tuple of fields to be used as <options>.
selected    - The value of the selected <option>.
error       - A list of error strings for the field or just true to highlight the field.
classes     - An array of classes to apply to the control-group.
is_required - Boolean of whether this input is requred for the form to validate

Examples:

  {% import 'macros/form.html' as form %}
  {{ form.select('year', label=_('Year'), options=[{'name':2010, 'value': 2010},{'name': 2011, 'value': 2011}], selected=2011, error=errors.year) }}

#}
{% macro select(name, id='', label='', options='', selected='', error='', classes=[], attrs={}, is_required=false) %}
  {% set classes = (classes|list) %}
  {% do classes.append('control-select') %}

  {%- set extra_html = caller() if caller -%}
  {% call input_block(id or name, label or name, error, classes, extra_html=extra_html, is_required=is_required) %}
    <select id="{{ id or name }}" name="{{ name }}" {{ attributes(attrs) }}>
      {% for option in options %}
        <option value="{{ option.value }}"{% if option.value == selected %} selected{% endif %}>{{ option.text or option.value }}</option>
      {% endfor %}
    </select>
  {% endcall %}
{% endmacro %}

{#
Creates all the markup required for a Markdown textarea element. Handles
matching labels to inputs, selected item and error messages.

name        - The name of the form parameter.
id          - The id to use on the input and label. Convention is to prefix with 'field-'.
label       - The human readable label.
value       - The value of the input.
placeholder - Some placeholder text.
error       - A list of error strings for the field or just true to highlight the field.
classes     - An array of classes to apply to the control-group.
is_required - Boolean of whether this input is requred for the form to validate

Examples:

  {% import 'macros/form.html' as form %}
  {{ form.markdown('desc', id='field-description', label=_('Description'), value=data.desc, error=errors.desc) }}

#}
{% macro markdown(name, id='', label='', value='', placeholder='', error="", classes=[], attrs={}, is_required=false) %}
  {% set classes = (classes|list) %}
  {% do classes.append('control-full') %}
  {% set markdown_tooltip = "<pre><p>__Bold text__ or _italic text_</p><p># title<br>## secondary title<br>### etc</p><p>* list<br>* of<br>* items</p><p>http://auto.link.ed/</p></pre><p><b><a href='http://daringfireball.net/projects/markdown/syntax' target='_blank'>Full markdown syntax</a></b></p><p class='muted'><b>Please note:</b> HTML tags are stripped out for security reasons</p>" %} 

  {%- set extra_html = caller() if caller -%}
  {% call input_block(id or name, label or name, error, classes, control_classes=["editor"], extra_html=extra_html, is_required=is_required) %}
    <textarea id="{{ id or name }}" name="{{ name }}" cols="20" rows="5" placeholder="{{ placeholder }}" {{ attributes(attrs) }}>{{ value | empty_and_escape }}</textarea>
    <span class="editor-info-block">{% trans %}You can use <a href="#markdown" title="Markdown quick reference" data-target="popover" data-content="{{ markdown_tooltip }}" data-html="true">Markdown formatting</a> here{% endtrans %}</span>
  {% endcall %}
{% endmacro %}

{#
Creates all the markup required for a plain textarea element. Handles
matching labels to inputs, selected item and error messages.

name        - The name of the form parameter.
id          - The id to use on the input and label. Convention is to prefix with 'field-'.
label       - The human readable label.
value       - The value of the input.
placeholder - Some placeholder text.
error       - A list of error strings for the field or just true to highlight the field.
classes     - An array of classes to apply to the control-group.
is_required - Boolean of whether this input is requred for the form to validate

Examples:

  {% import 'macros/form.html' as form %}
  {{ form.textarea('desc', id='field-description', label=_('Description'), value=data.desc, error=errors.desc) }}

#}
{% macro textarea(name, id='', label='', value='', placeholder='', error="", classes=[], attrs={}, is_required=false, rows=5, cols=20) %}
  {% set classes = (classes|list) %}
  {% do classes.append('control-full') %}

  {%- set extra_html = caller() if caller -%}
  {% call input_block(id or name, label or name, error, classes, extra_html=extra_html, is_required=is_required) %}
    <textarea id="{{ id or name }}" name="{{ name }}" cols="{{ cols }}" rows="{{ rows }}" placeholder="{{ placeholder }}" {{ attributes(attrs) }}>{{ value | empty_and_escape }}</textarea>
  {% endcall %}
{% endmacro %}

{#
Creates all the markup required for an input element with a prefixed segment.
These are useful for showing url slugs and other fields where the input
information forms only part of the saved data.

name        - The name of the form parameter.
id          - The id to use on the input and label. Convention is to prefix with 'field-'.
label       - The human readable label.
prepend     - The text that will be prepended before the input.
value       - The value of the input.
              which will use the name key as the value.
placeholder - Some placeholder text.
error       - A list of error strings for the field  or just true to highlight the field.
classes     - An array of classes to apply to the control-group.
is_required - Boolean of whether this input is requred for the form to validate

Examples:

  {% import 'macros/form.html' as form %}
  {{ form.prepend('slug', id='field-slug', prepend='/dataset/', label=_('Slug'), value=data.slug, error=errors.slug) }}

#}
{% macro prepend(name, id='', label='', prepend='', value='', placeholder='', type='text', error="", classes=[], attrs={}, is_required=false) %}
  {# We manually append the error here as it needs to be inside the .input-prepend block #}
  {% set classes = (classes|list) %}
  {% do classes.append('error') if error %}
  {%- set extra_html = caller() if caller -%}
  {% call input_block(id or name, label or name, error='', classes=classes, extra_html=extra_html, is_required=is_required) %}
    <div class="input-prepend">
      {% if prepend %}<span class="add-on">{{ prepend }}</span>{%- endif -%}
      <input id="{{ id or name }}" type="{{ type }}" name="{{ name }}" value="{{ value | empty_and_escape }}" placeholder="{{ placeholder }}" {{ attributes(attrs) }} />
      {% if error and error is iterable %}<span class="error-block">{{ error|join(', ') }}</span>{% endif %}
    </div>
  {% endcall %}
{% endmacro %}

{#
Creates all the markup required for an custom key/value input. These are usually
used to let the user provide custom meta data. Each "field" has three inputs
one for the key, one for the value and a checkbox to remove it. So the arguments
for this macro are nearly all tuples containing values for the
(key, value, delete) fields respectively.

name        - A tuple of names for the three fields.
id          - An id string to be used for each input.
label       - The human readable label for the main label.
values      - A tuple of values for the (key, value, delete) fields. If delete
              is truthy the checkbox will be checked.
placeholder - A tuple of placeholder text for the (key, value) fields.
error       - A list of error strings for the field or just true to highlight the field.
classes     - An array of classes to apply to the control-group.
is_required - Boolean of whether this input is requred for the form to validate

Examples:

  {% import 'macros/form.html' as form %}
  {{ form.custom(
    names=('custom_key', 'custom_value', 'custom_deleted'),
    id='field-custom',
    label=_('Custom Field'),
    values=(extra.key, extra.value, extra.deleted),
    error=''
  ) }}
#}
{% macro custom(names=(), id="", label="", values=(), placeholders=(), error="", classes=[], attrs={}, is_required=false, key_values=()) %}
  {%- set classes = (classes|list) -%}
  {%- set label_id = (id or names[0]) ~ "-key" -%}
  {%- set extra_html = caller() if caller -%}
  {%- do classes.append('control-custom') -%}

  {% call input_block(label_id, label or name, error, classes, control_classes=["editor"], extra_html=extra_html, is_required=is_required) %}
    <div class="input-prepend" {{ attributes(attrs) }}>
      <label for="{{ label_id }}" class="add-on">Key</label><input id="{{ id or names[0] }}-key" type="text" name="{{ names[0] }}" value="{{ values[0] | empty_and_escape }}" placeholder="{{ placeholders[0] }}" />
      <label for="{{ id or names[1] }}-value" class="add-on">Value</label><input id="{{ id or names[1] }}-value" type="text" name="{{ names[1] }}" value="{{ values[1] | empty_and_escape }}" placeholder="{{ placeholders[1] }}" />
      {% if values[0] or values[1] or error %}
        <label class="checkbox" for="{{ id or names[2] }}-remove">
          <input type="checkbox" id="{{ id or names[2] }}-remove" name="{{ names[2] }}"{% if values[2] %} checked{% endif %} /> <span>{{ _('Remove') }}</span>
        </label>
      {% endif %}
    </div>
  {% endcall %}
{% endmacro %}

{#
A generic input_block for providing the default markup for CKAN form elements.
It is expected to be called using a {% call %} block, the contents of which
will be inserted into the .controls element.

for     - The id for the input that the label should match.
label   - A human readable label.
error   - A list of error strings for the field or just true.
classes - An array of custom classes for the outer element.
control_classes - An array of custom classes for the .control wrapper.
extra_html - An html string to be inserted after the errors eg. info text.
is_required - Boolean of whether this input is requred for the form to validate

Example:

  {% import 'macros/form.html' as form %}
  {% call form.input_block("field", "My Field") %}
    <input id="field" type="text" name="{{ name }}" value="{{ value | empty_and_escape }}" />
  {% endcall %}

#}
{% macro input_block(for, label="", error="", classes=[], control_classes=[], extra_html="", is_required=false) %}
  <div class="control-group{{ " error" if error }}{{ " " ~ classes | join(' ') }}">
    <label class="control-label" for="{{ for }}">{% if is_required %}<span title="{{ _("This field is required") }}" class="control-required">*</span> {% endif %}{{ label or _('Custom') }}</label>
    <div class="controls{{ " " ~ control_classes | join(' ') }}">
      {{ caller() }}
      {% if error and error is iterable %}<span class="error-block">{{ error|join(', ') }}</span>{% endif %}
      {{ extra_html }}
    </div>
  </div>
{% endmacro %}

{#
Builds a list of errors for the current form.

errors  - A dict of field/message pairs.
type    - The alert-* class that should be applied (default: "error")
classes - A list of classes to apply to the wrapper (default: [])

Example:

  {% import 'macros/form.html' as form %}
  {{ form.errors(error_summary, type="warning") }}

#}
{% macro errors(errors={}, type="error", classes=[]) %}
  {% if errors %}
    <div class="error-explanation alert alert-{{ type }}{{ " " ~ classes | join(' ') }}">
      <p>{{ _('The form contains invalid entries:') }}</p>
      <ul>
        {% for key, error in errors.items() %}
          <li data-field-label="{{ key }}">{% if key %}{{ key }}: {% endif %}{{ error }}</li>
        {% endfor %}
      </ul>
    </div>
  {% endif %}
{% endmacro %}

{#
Renders an info box with a description. This will usually be used with in a
call block when creating an input element.

text    - The text to include in the box.
inline  - If true displays the info box inline with the input.
classes - A list of classes to add to the info box.

Example

  {% import 'macros/form.html' as form %}
  {% call form.input('name') %}
    {{ form.info(_('My useful help text')) }}
  {% endcall %}

#}
{% macro info(text='', inline=false, classes=[]) %}
  {%- if text -%}
    <div class="info-block{{ ' info-inline' if inline }}{{ " " ~ classes | join(' ') }}">
      <i class="icon-info-sign"></i>
      {{ text }}
    </div>
  {%- endif -%}
{% endmacro %}

{#
Builds a single hidden input.

name  - name of the hidden input
value - value of the hidden input

Example
  {% import 'macros/form.html' as form %}
  {{ form.hidden('name', 'value') }}

#}
{% macro hidden(name, value) %}
  <input type="hidden" name="{{ name }}" value="{{ value }}" />
{% endmacro %}

{#
Contructs hidden inputs for each name-value pair.

fields - [('name1', 'value1'), ('name2', 'value2'), ...]

Two parameter for excluding several names or name-value pairs.

except_names - list of names to be excluded
except       - list of name-value pairs to be excluded


Example:
    {% import 'macros/form.html' as form %}
    {% form.hidden_from_list(fields=c.fields, except=[('topic', 'xyz')]) %}
    {% form.hidden_from_list(fields=c.fields, except_names=['time_min', 'time_max']) %}
#}
{% macro hidden_from_list(fields, except_names=None, except=None) %}
  {% set except_names = except_names or [] %}
  {% set except = except or [] %}

  {% for name, value in fields %}
    {% if name and value and name not in except_names and (name, value) not in except %}
      {{ hidden(name, value) }}
    {% endif %}
  {% endfor %}
{% endmacro %}

{#
Builds a space seperated list of html attributes from a dict of key/value pairs.
Generally only used internally by macros.

attrs - A dict of attribute/value pairs

Example

  {% import 'macros/form.html' as form %}
  {{ form.attributes({}) }}

#}
{%- macro attributes(attrs={}) -%}
  {%- for key, value in attrs.items() -%}
  {{ " " }}{{ key }}{% if value != "" %}="{{ value }}"{% endif %}
  {%- endfor -%}
{%- endmacro -%}

{#
Outputs the "* Required field" message for the bottom of formss

Example
  {% import 'macros/form.html' as form %}
  {{ form.required_message() }}

#}
{% macro required_message() %}
  <p class="control-required-message">
    <span class="control-required">*</span> {{ _("Required field") }}
  </p>
{% endmacro %}

{#
Builds a file upload for input

Example
  {% import 'macros/form.html' as form %}
  {{ form.image_upload(data, errors, is_upload_enabled=true) }}

#}
{% macro image_upload(data, errors, field_url='image_url', field_upload='image_upload', field_clear='clear_upload',
                      is_url=false, is_upload=false, is_upload_enabled=false, placeholder=false,
                      url_label='', upload_label='')  %}
  {% set placeholder = placeholder if placeholder else _('http://example.com/my-image.jpg') %}
  {% set url_label = url_label or _('Image URL')  %}
  {% set upload_label = upload_label or _('Image')  %}

  {% if is_upload_enabled %}
  <div class="image-upload" data-module="image-upload" data-module-is_url="{{ 'true' if is_url else 'false' }}" data-module-is_upload="{{ 'true' if is_upload else 'false' }}"
       data-module-field_url="{{ field_url }}" data-module-field_upload="{{ field_upload }}" data-module-field_clear="{{ field_clear }}" data-module-upload_label="{{ upload_label }}">
  {% endif %}

  {{ input(field_url, label=url_label, id='field-image-url', placeholder=placeholder, value=data.get(field_url), error=errors.get(field_url), classes=['control-full']) }}

  {% if is_upload_enabled %}
    {{ input(field_upload, label=upload_label, id='field-image-upload', type='file', placeholder='', value='', error='', classes=['control-full']) }}
    {% if is_upload %}
      {{ checkbox(field_clear, label=_('Clear Upload'), id='field-clear-upload', value='true', error='', classes=['control-full']) }}
    {% endif %}
  {% endif %}

  {% if is_upload_enabled %}</div>{% endif %}

{% endmacro %}
