{% load i18n admin_urls admin_static super_inlines grp_tags %}

<style>
  .grp-group .grp-group {
    margin: 20px;
    width: initial;
  }
</style>

{% with inline=inline_admin_formset.opts formset=inline_admin_formset.formset %}
  {% if not formset.has_parent or is_subinline %}
    <div class="grp-group grp-stacked {% if inline.classes %}{{ inline.classes|join:" " }}{% endif %}" id="{{ formset.prefix }}-group"  data-inline-type="stacked" data-prefix="{{ formset.prefix }}" data-remove-text="{% trans "Remove" %}" data-add-text="{% blocktrans with verbose_name=inline.verbose_name|capfirst %}Add another {{ verbose_name }}{% endblocktrans %}" data-related-lookup-fields-fk='{% get_related_lookup_fields_fk inline %}' data-related-lookup-fields-m2m='{% get_related_lookup_fields_m2m inline %}' data-related-lookup-fields-generic='{% get_related_lookup_fields_generic inline %}' data-autocomplete-lookup-fields-fk='{% get_autocomplete_lookup_fields_fk inline %}' data-autocomplete-lookup-fields-m2m='{% get_autocomplete_lookup_fields_m2m inline %}' data-autocomplete-lookup-fields-generic='{% get_autocomplete_lookup_fields_generic inline %}'>
      <h2 class="grp-collapse-handler">{% if inline.title %}{{ inline.title }}{% else %}{{ inline.verbose_name_plural|capfirst }}{% endif %}</h2>
      <ul class="grp-tools">
          <li><a href="javascript://" class="grp-icon grp-open-handler" title="{% trans 'Open All Items' %}"></a></li>
          <li><a href="javascript://" class="grp-icon grp-close-handler" title="{% trans 'Close All Items' %}"></a></li>
          <li><a href="javascript://" class="grp-icon grp-add-handler" title="{% trans 'Add Item' %}"> </a></li>
      </ul>
      {{ formset.management_form }}
      {{ formset.non_form_errors }}

      <div class="grp-items">
        {% with sortable_field_name=inline.sortable_field_name|default:'' %}
          {% for inline_admin_form in inline_admin_formset|formsetsort:sortable_field_name %}
            {% with original=inline_admin_form.original model_admin=inline_admin_form.model_admin %}
              <div class="grp-module {{ inline.inline_classes|join:" "|default:"grp-collapse grp-closed" }}{% if original or inline_admin_form.show_url %} has_original grp-dynamic-form{% endif %}{% if forloop.last %} grp-empty-form{% endif %}" id="{{ formset.prefix }}{% if forloop.last %}-__prefix__{% else %}{{ forloop.counter0 }}{% endif %}">
                <h3 class="grp-collapse-handler">{{ inline.verbose_name }}&nbsp;&nbsp;{% if original %}{{ original }}{% endif %}</h3>
                <ul class="grp-tools">
                  {% if inline_admin_form.show_url %}<li><a href="{% url 'admin:view_on_site' inline_admin_form.original_content_type_id original.pk %}" class="grp-icon grp-viewsite-link" title="{% trans 'View on Site' %}" target="_blank"></a></li>{% endif %}
                  {% if inline.sortable_field_name %}
                    <li><a href="javascript://" class="grp-icon grp-drag-handler" title="{% trans 'Move Item' %}"></a></li>
                  {% endif %}
                  {% if original %}
                    {% if formset.can_delete %}
                      <li class="grp-delete-handler-container">{{ inline_admin_form.deletion_field.field }}<a href="javascript://" class="grp-icon grp-delete-handler" title="{% trans 'Delete Item' %}"></a></li>
                    {% else %}
                      <li><span class="grp-icon">&nbsp;</span></li>
                    {% endif %}
                  {% else %}
                    <li><a href="javascript://" class="grp-icon grp-remove-handler" title="{% trans 'Delete Item' %}"></a></li>
                  {% endif %}
                </ul>
                {% if inline_admin_form.form.non_field_errors %}
                  {{ inline_admin_form.form.non_field_errors }}
                {% endif %}
                {% for fieldset in inline_admin_form %}
                  {% include "admin/includes/fieldset_inline.html" %}
                {% endfor %}
                {{ inline_admin_form.fk_field.field }}
                {% if inline_admin_form.has_auto_field or inline_admin_form.needs_explicit_pk_field %}{{ inline_admin_form.pk_field.field }}{% endif %}

                {% get_sub_inline_formsets inline original forloop.counter0 forloop.last as sub_inlines %}
                {% for sub_inline in sub_inlines %}
                  {% include sub_inline.opts.template with inline_admin_formset=sub_inline is_subinline=True %}
                {% endfor %}

              </div>
            {% endwith %}
          {% endfor %}
          {{ inline_admin_formset.extra_forms }}
        {% endwith %}
      </div>
      <div class="grp-module grp-transparent">
        <div class="grp-row">
          <a href="javascript://" class="grp-add-handler"><strong>{% blocktrans with inline.verbose_name as verbose_name %}Add another {{ verbose_name }}{% endblocktrans %}</strong></a>
          <ul class="grp-tools">
            <li><a href="javascript://" class="grp-icon grp-add-handler" title="{% trans 'Add Item' %}"> </a></li>
          </ul>
        </div>
      </div>

    </div>


    {% if not is_subinline %}
    <script type="text/javascript">
    (function($) {
          function onAfterAdd ($formset, $form, prefix, isInitial) {
            var related_lookup_fields_fk = $formset.data('related-lookup-fields-fk');
            var related_lookup_fields_m2m = $formset.data('related-lookup-fields-m2m');
            var related_lookup_fields_generic = $formset.data('related-lookup-fields-generic');
            var autocomplete_fields_fk = $formset.data('autocomplete-lookup-fields-fk');
            var autocomplete_fields_m2m = $formset.data('autocomplete-lookup-fields-m2m');
            var autocomplete_fields_generic = $formset.data('autocomplete-lookup-fields-generic');
            grappelli.reinitDateTimeFields($form);
            grappelli.updateSelectFilter($form);
            $.each(related_lookup_fields_fk, function() {
                $form.find("input[name^='" + prefix + "'][name$='-" + this + "']")
                .grp_related_fk({lookup_url:"{% url 'grp_related_lookup' %}"});
            });
            $.each(related_lookup_fields_m2m, function() {
                $form.find("input[name^='" + prefix + "'][name$='-" + this + "']")
                .grp_related_m2m({lookup_url:"{% url 'grp_m2m_lookup' %}"});
            });
            $.each(related_lookup_fields_generic, function() {
                var content_type = this[0],
                    object_id = this[1];
                $form.find("input[name^='" + prefix + "'][name$='-" + this[1] + "']")
                .each(function() {
                    var i = $(this).attr("id").match(/-\d+-/);
                    if (i) {
                        var ct_id = "#id_" + prefix + i[0] + content_type,
                            obj_id = "#id_" + prefix + i[0] + object_id;
                        $(this).grp_related_generic({content_type:ct_id, object_id:obj_id, lookup_url:"{% url 'grp_related_lookup' %}"});
                    }
                });
            });
            $.each(autocomplete_fields_fk, function() {
                $form.find("input[name^='" + prefix + "'][name$='-" + this + "']")
                .each(function() {
                    $(this).grp_autocomplete_fk({
                        lookup_url:"{% url 'grp_related_lookup' %}",
                        autocomplete_lookup_url:"{% url 'grp_autocomplete_lookup' %}"
                    });
                });
            });
            $.each(autocomplete_fields_m2m, function() {
                $form.find("input[name^='" + prefix + "'][name$='-" + this + "']")
                .each(function() {
                    $(this).grp_autocomplete_m2m({
                        lookup_url:"{% url 'grp_m2m_lookup' %}",
                        autocomplete_lookup_url:"{% url 'grp_autocomplete_lookup' %}"
                    });
                });
            });
            $.each(autocomplete_fields_generic, function() {
                var content_type = this[0],
                    object_id = this[1];
                $form.find("input[name^='" + prefix + "'][name$='-" + this[1] + "']")
                .each(function() {
                    var i = $(this).attr("id").match(/-\d+-/);
                    if (i) {
                        var ct_id = "#id_" + prefix + i[0] + content_type,
                            obj_id = "#id_" + prefix + i[0] + object_id;
                        $(this).grp_autocomplete_generic({
                            content_type:ct_id,
                            object_id:obj_id,
                            lookup_url:"{% url 'grp_related_lookup' %}",
                            autocomplete_lookup_url:"{% url 'grp_autocomplete_lookup' %}"
                        });
                    }
                });
            });
            if (!isInitial) {
              $form.grp_collapsible();
              $form.find(".grp-collapse").grp_collapsible();
            }
          }

        function postInit ($formset, prefix) {
          {% if inline.sortable_field_name %}
            $formset.find("> div.grp-items").sortable({
                handle: "a.grp-drag-handler",
                items: "div.grp-dynamic-form",
                axis: "y",
                appendTo: 'body',
                forceHelperSize: true,
                placeholder: 'grp-module ui-sortable-placeholder',
                forcePlaceholderSize: true,
                containment: '#{{ formset.prefix }}-group > div.grp-items',
                tolerance: 'pointer',
                start: function(evt, ui) {
                    ui.placeholder.height(ui.item.height() + 12);
                }
            });
            /*
            Enables changing the sort order manually on sort field change
            - Top entry is 0
            - Last entry is n-1. Or any number that equals or is greater than n.
            - Sortables without a value (extra forms) are not respected. If they are at the end, they stay there.
            - Non-Number and negative numbers are being ignored.
            - It does not cleans up the order field values on change (just like dragging does not do that).
            */
            $.fn.grp_reverse_list = [].reverse;
            $formset
                .find("div.grp-row.{{ inline.sortable_field_name }} :input")
                .each(function(i, item) {
                    $(item).bind('change', function(event) {
                        var desired_index = $(event.target).val() * 1;
                        if(!isNaN(desired_index) && desired_index >= 0) {
                            var $row = $(event.target).parents('div.grp-dynamic-form');
                            var $table = $row.parents('div.grp-items.ui-sortable');
                            $row.detach();
                            var $row_desired = $table.children('div.grp-dynamic-form').get(desired_index);
                            if($row_desired) {
                                $row.insertBefore($row_desired);
                                $row.find('h3,div.grp-row').effect('highlight', {color:"#ffffcc"}, 2000);
                            } else {
                                // FIXME: this appends the new row to the very end of the table.
                                // instead, it should be added after the last row with values.
                                $table.append($row);
                                $row.find('h3,div.grp-row').effect('highlight', {color:"#ffffcc"}, 2000);
                            }
                        }
                    });
                });
            $("#{{ opts.model_name }}_form").bind("submit", function(){
                var sortable_field_name = "{{ inline.sortable_field_name }}",
                    sortable_excludes = {% get_sortable_excludes inline %},
                    i = 0;
                $formset.find("div.grp-dynamic-form").each(function(){
                    var fields = $(this).find("fieldset :input[type!=radio][type!=checkbox],input:checked,input[type=file]"),
                        submit_values = false,
                        has_value;
                    $(fields).each(function() {
                        // position is being updated if
                        // a) the field has a value
                        // b) if the field is not exluded with sortable_excludes (e.g. with default values)
                        has_value = $(this).val() || ($(this).attr('type') == 'file' && $(this).siblings('a').length);
                        if (has_value && $(this).attr("name") && $.inArray($(this).attr("name").split("-").pop(), sortable_excludes) == -1) {
                            submit_values = true;
                        }
                    });
                    if (submit_values) {
                        $(this).find("input[name$='"+sortable_field_name+"']").val(i);
                        i++;
                    }
                });
            });
          {% endif %}
        }

        $("#{{ formset.prefix }}-group").formset(onAfterAdd, postInit);

    })(grp.jQuery);
    </script>
    {% endif %}

  {% endif %}
{% endwith %}
