{% extends "base.html" %}

{% block js_media %}
    <script type="text/javascript">
        window.valid_files = {{valid_files_json}};

        $(function () {
        });
    </script>
    <script type="text/javascript" src="{{ static('libs/jquery-sortable.js') }}"></script>
    <script type="text/javascript" src="{{ static('libs/featherlight/featherlight.min.js') }}"></script>
    <script type="text/javascript">
        $(function () {
            function update_select2() {
                $('tbody:not(.extra-row-body) .type-column select').select2({
                    minimumResultsForSearch: -1
                });
            }

            update_select2();

            function autofill_if_exists($select, file) {
                if (!$select.val() && ~window.valid_files.indexOf(file))
                    $select.val(file).trigger('change');
            }

            var $table = $('#case-table');
            $table.on('add-row', function (e, $tr) {
                update_select2();
                $tr.find('input').filter('[id$=file]').each(function () {
                    var $select, val = $(this).replaceWith($select = $('<select>').attr({
                        id: $(this).attr('id'),
                        name: $(this).attr('name'),
                        style: 'width: 100%'
                    })).val();
                    $select.select2({
                        data: window.valid_files,
                        allowClear: true,
                        placeholder: ''
                    }).val(val).trigger('change').on('change', function () {
                        var val = $select.val();
                        if (val) {
                            if ($select.attr('id').endsWith('input_file'))
                                autofill_if_exists($tr.find('select[id$=output_file]'), val.replace(/in(?!.*?in)/, 'out'));
                            else
                                autofill_if_exists($tr.find('select[id$=input_file]'), val.replace(/out(?!.*?out)/, 'in'));
                        }
                    });
                });
            });

            var order = 0;

            function handle_table_reorder() {
                var in_batch = false;
                $table.find('tbody:first tr').each(function () {
                    switch ($(this).attr('data-type')) {
                        case 'C':
                            $(this).find('input[id$=points], input[id$=pretest]').toggle(!in_batch);
                            break;
                        case 'S':
                            in_batch = true;
                            break;
                        case 'E':
                            in_batch = false;
                    }
                });
            }

            function try_parse_json(json) {
                try {
                    return JSON.parse(json);
                } catch (e) {
                    return {};
                }
            }

            function checker_precision($checker) {
                var $td = $checker.parent();
                var $args = $td.find('input');
                var $precision = $('<input>', {
                    type: 'number',
                    value: try_parse_json($args.val()).precision || 6,
                    title: 'precision (decimal digits)',
                    style: 'width: 4em'
                }).change(function () {
                    if ($checker.val().startsWith('floats'))
                        $args.val(JSON.stringify({precision: parseInt($(this).val())}));
                    else
                        $args.val('');
                }).appendTo($td);

                $checker.change(function () {
                    $precision.toggle($checker.val().startsWith('floats')).change();
                }).change();
            }

            function swap_row($a, $b) {
                var $a_order = $a.find('input[id$=order]'), $b_order = $b.find('input[id$=order]');
                var order = $a_order.val();
                $a_order.val($b_order.val());
                $b_order.val(order);
                $b.after($a);
                $a.find('span.order').text($a_order.val());
                $b.find('span.order').text($b_order.val());
                handle_table_reorder();
            }

            checker_precision($('#id_problem-data-checker'));

            $table.on('add-row', function (e, $tr) {
                var $order = $tr.find('input').filter('[id$=order]').attr('type', 'hidden').val(++order);
                $order.after($('<span>', {'class': 'order'}).text($order.val()))
                    .after($('<i>', {'class': 'fa fa-fw fa-lg fa-ellipsis-v'}));

                var $opts = $tr.find('input').slice(2, 6);
                var $files = $tr.find('select').slice(1, 3);
                var $checker = $files.end().last();
                $tr.find('select[id$=type]').change(function () {
                    var $this = $(this), val = $this.val(), disabled;
                    switch (val) {
                        case 'S':
                        case 'E':
                            disabled = val == 'S';
                            $opts.toggle(val == 'S');
                            $files.siblings('.select2').hide();
                            $checker.toggle(val == 'S');
                            break;
                        default:
                            $opts.toggle(val == 'C');
                            $files.siblings('.select2').toggle(val == 'C');
                            $checker.toggle(val == 'C');
                            var $prevs = $tr.prevAll('tr[data-type=S], tr[data-type=E]');
                            disabled = $prevs.length && $prevs.get(0).getAttribute('data-type') == 'S';
                            $tr.find('input[id$=points], input[id$=pretest]').toggle(val == 'C' && !disabled);
                    }
                    $tr.attr('data-type', val).nextUntil('tr[data-type=S], tr[data-type=E], tr[data-type=""]')
                        .find('input[id$=points], input[id$=pretest]').toggle(!disabled);
                }).change();

                var tooltip_classes = 'tooltipped tooltipped-s';
                $tr.find('a.edit-generator-args').mouseover(function () {
                    switch ($tr.attr('data-type')) {
                        case 'C':
                        case 'S':
                            var $this = $(this).addClass(tooltip_classes);
                            $this.attr('aria-label', $this.prev().val() || '(none)');
                    }
                }).mouseout(function () {
                    $(this).removeClass(tooltip_classes).removeAttr('aria-label');
                }).featherlight($('.generator-args-editor'), {
                    beforeOpen: function () {
                        switch ($tr.attr('data-type')) {
                            case 'C':
                            case 'S':
                                return true;
                            default:
                                return false;
                        }
                    },
                    afterOpen: function () {
                        var $input = this.$currentTarget.prev();
                        this.$instance.find('.generator-args-editor')
                            .find('textarea').val($input.val()).end()
                            .find('.button').click(function () {
                            $input.val($(this).prev().val());
                            $.featherlight.current().close();
                        }).end()
                            .show();
                    }
                });

                checker_precision($tr.find('select[id$=checker]'));
            }).find('tbody:first').find('tr').each(function () {
                $table.trigger('add-row', [$(this)]);
            });

            $('form').submit(function () {
                $table.find('tbody:first').find('tr').each(function () {
                    var filled = false;
                    $(this).find('input, select').each(function () {
                        var $this = $(this);
                        if (!$this.attr('name'))
                            return;
                        if ($this.attr('type') === 'checkbox')
                            filled |= $this.is(':checked');
                        else if (!$this.attr('name').endsWith('order'))
                            filled |= !!$this.val();
                    });
                    if (!filled)
                        $(this).find('input[id$=order]').val('');
                });
            });

            var $total = $('#id_cases-TOTAL_FORMS');

            $('a#add-case-row').click(function () {
                var $tr;
                $table.find('tbody:first').append($tr = $($table.find('.extra-row-body').html()
                    .replace(/__prefix__/g, $total.val())));
                $tr.find('.type-column select option[value="C"]').attr('selected', true);
                $total.val(parseInt($total.val()) + 1);
                $table.trigger('add-row', [$tr]);
                window.scrollBy(0, $tr.height());
                return false;
            });

            $('a#fill-testcases').click(function () {
                var inFiles = [], outFiles = [];
                for (var i = 0; i < window.valid_files.length; i++) {
                    if (window.valid_files[i].endsWith(".in")) {
                        inFiles.push(window.valid_files[i]);
                    }
                    if (window.valid_files[i].endsWith(".out")) {
                        outFiles.push(window.valid_files[i]);
                    }
                }
                if (inFiles.length == 0) {
                    alert("No input/output files. Make sure your files' suffices are .in/.out");
                    return false;
                }
                if (inFiles.length != outFiles.length) {
                    alert("The input files do not match the output files!");
                    return false;
                }
                // add boxes
                while ($total.val() < inFiles.length) {
                    $('a#add-case-row').click();
                }
                // fill cases
                for (var i = 0; i < inFiles.length; i++) {
                    $("#id_cases-" + i + "-input_file").val(inFiles[i]).change();
                }
                // add points
                if ($('#problem-type').val() == "ICPC") {
                    for (i = 0; i + 1 < inFiles.length; i++) {
                        $("#id_cases-" + i + "-points").val("0").change();
                    }
                    $("#id_cases-" + (inFiles.length - 1) + "-points").val("100").change();
                }
                else {
                    for (i = 0; i < inFiles.length; i++) {
                        $("#id_cases-" + i + "-points").val("1").change();
                    }
                }
                return false;
            });

            var oldIndex;
            $table.sortable({
                containerSelector: 'table',
                itemPath: '> tbody:first',
                itemSelector: 'tr',
                handle: 'i.fa-ellipsis-v',
                placeholder: '<tr class="placeholder">',
                onDragStart: function ($item, container, _super) {
                    oldIndex = $item.index();
                    _super($item, container);
                },
                onDrop: function ($item, container, _super) {
                    var newIndex = $item.index();
                    if (newIndex > oldIndex) {
                        var order = parseInt($item.parent().children().slice(oldIndex, newIndex).each(function () {
                            var $order = $(this).find('input[id$=order]');
                            $order.val(parseInt($order.val()) - 1).siblings('span.order').text($order.val());
                        }).last().after($item).find('input[id$=order]').val());
                        $item.find('input[id$=order]').val(order + 1).siblings('span.order').text(order + 1);
                    } else if (newIndex < oldIndex) {
                        var order = parseInt($item.parent().children().slice(newIndex + 1, oldIndex + 1).each(function () {
                            var $order = $(this).find('input[id$=order]');
                            $order.val(parseInt($order.val()) + 1).siblings('span.order').text($order.val());
                        }).first().before($item).find('input[id$=order]').val());
                        $item.find('input[id$=order]').val(order - 1).siblings('span.order').text(order - 1);
                    }
                    if (newIndex != oldIndex)
                        handle_table_reorder();
                    _super($item, container);
                }
            });

            var $controls = $('#column-visible');
            var problem = $controls.attr('data-problem');
            $controls.find('input').change(function () {
                var $this = $(this), suffix = $this.attr('data-suffix'), checked = $this.is(':checked');
                $table.find('.' + suffix.replace(/_/g, '-')).toggle(checked);
                localStorage.setItem('data-visible:' + problem + ':' + suffix, checked ? '1' : '0')
            }).each(function () {
                var $this = $(this), suffix = $this.attr('data-suffix'), filled = false;
                filled = localStorage.getItem('data-visible:' + problem + ':' + suffix);
                if (filled !== null)
                    filled = filled == '1';
                else {
                    filled = false;
                    $table.find('[id$=' + suffix + ']').each(function () {
                        filled |= !!$(this).val();
                    });
                }
                $this.prop('checked', filled).trigger('change');
            });
        });
    </script>
{% endblock %}

{% block media %}
    <style>
        #case-table .select2 {
            text-align: initial;
        }

        .order-column {
            width: 1em;
        }

        .bad-file input, .bad-file .select2-selection {
            border-color: red;
        }

        span.order {
            padding-right: 0.5em;
        }

        body.dragging, body.dragging * {
            cursor: move !important;
        }

        .dragged {
            position: absolute;
            opacity: 0.5;
            z-index: 2000;
        }

        tr.placeholder {
            display: block;
            background: red;
            position: relative;
            margin: 0;
            padding: 0;
            border: none;
        }

        tr.placeholder:before {
            content: "";
            position: absolute;
            width: 0;
            height: 0;
            border: 5px solid transparent;
            border-left-color: red;
            margin-top: -5px;
            left: -5px;
            border-right: none;
        }

        i.fa-ellipsis-v {
            cursor: move;
        }

        .edit-generator-args {
            position: relative;
        }

        .generator-args-editor textarea {
            display: block;
            width: 100%;
            margin-bottom: 0.5em;
            height: 8em;
        }

        .generator-args-editor #submit-button {
            display: block;
            float: right;
        }

        #case-table tbody td {
            white-space: nowrap;
        }

        .type-column {
            width: 8em;
        }

        ul.errorlist {
            border: 3px red solid;
            border-radius: 5px;
            padding-top: 1em;
            padding-bottom: 1em;
            background: #e99;
        }
    </style>
{% endblock %}

{% block header %}
    {% if data_form.instance.has_yml %}
        <div class="title-line-action">
            [<a href="{{ url('problem_data_init', problem.code) }}">{{ _('View YAML') }}</a>]
        </div>
    {% endif %}
{% endblock %}

{% block body %}
    {% if data_form.instance.feedback %}
        <ul class="errorlist">
            <li>{{ data_form.instance.feedback }}</li>
        </ul>
    {% endif %}
    <form action="" method="POST" enctype="multipart/form-data">
        {% csrf_token %}
        {{ cases_formset.management_form }}
        <table class="table">
            {{ data_form.as_table() }}
            <th>
                <label>Autofill testcases:</label>
            </th>
            <td>
                Problem type:
                <select id="problem-type">
                    <option value="ICPC">ICPC</option>
                    <option value="OI">OI</option>
                </select>
                <a id="fill-testcases" href="#">
                    <i class="fa fa-circle"></i>
                    Fill testcases
                </a>
            </td>
        </table>
        <div id="column-visible" data-problem="{{ problem.code }}">
            <strong>{{ _('Show columns:') }}</strong>
            <label>
                <input type="checkbox" data-suffix="output_prefix">
                {{ _('Output prefix') }}
            </label>
            <label>
                <input type="checkbox" data-suffix="output_limit">
                {{ _('Output limit') }}
            </label>
            <label>
                <input type="checkbox" data-suffix="checker">
                {{ _('Checker') }}
            </label>
            <label>
                <input type="checkbox" data-suffix="generator_args">
                {{ _('Generator args') }}
            </label>
        </div>
        <table id="case-table" class="table">
            <thead>
            <tr>
                <th class="order-column"></th>
                <th class="type-column">{{ _('Type') }}</th>
                <th>{{ _('Input file') }}</th>
                <th>{{ _('Output file') }}</th>
                <th>{{ _('Points') }}</th>
                <th>{{ _('Pretest?') }}</th>
                <th class="output-prefix">{{ _('Output prefix') }}</th>
                <th class="output-limit">{{ _('Output limit') }}</th>
                <th class="checker">{{ _('Checker') }}</th>
                <th class="generator-args">{{ _('Generator args') }}</th>
                {% if cases_formset.can_delete %}
                    <th>{{ _('Delete?') }}</th>
                {% endif %}
            </tr>
            </thead>
            <tbody>
            {% for form in all_case_forms %}
                {% if form.non_field_errors() %}
                    <tr>
                        <td colspan="{{ 9 + cases_formset.can_delete }}">{{ form.non_field_errors() }}</td>
                    </tr>
                {% endif %}
                {% if form.prefix and '__prefix__' in form.prefix %}
                    </tbody>
                    <tbody class="extra-row-body" style="display: none">
                {% endif %}
                <tr data-type="{{ form['type'].value() }}">
                    <td>{{ form.id }}{{ form.order.errors }}{{ form.order }}</td>
                    <td class="type-column">{{ form.type.errors }}{{ form.type }}</td>
                    <td{% if not (form.empty_permitted or form['type'].value() != 'C' or
                                  form['input_file'].value() in valid_files) %} class="bad-file"{% endif %}>
                        {{ form.input_file.errors }}{{ form.input_file }}
                    </td>
                    <td{% if not (form.empty_permitted or form['type'].value() != 'C' or
                                  form['output_file'].value() in valid_files) %} class="bad-file"{% endif %}>
                        {{ form.output_file.errors }}{{ form.output_file }}
                    </td>
                    <td>{{ form.points.errors }}{{ form.points }}</td>
                    <td>{{ form.is_pretest.errors }}{{ form.is_pretest }}</td>
                    <td class="output-prefix">{{ form.output_prefix.errors }}{{ form.output_prefix }}</td>
                    <td class="output-limit">{{ form.output_limit.errors }}{{ form.output_limit }}</td>
                    <td class="checker">
                        {{ form.checker.errors }}{{ form.checker }}{{ form.checker_args.errors }}{{ form.checker_args }}
                    </td>
                    <td class="generator-args">{{ form.generator_args.errors }}{{ form.generator_args }}
                        <a href="javascript:void(0)" class="edit-generator-args">
                            <i class="fa fa-pencil"></i>
                            {{ _('Edit') }}
                        </a>
                    </td>
                    {% if cases_formset.can_delete %}
                        <td>{{ form.DELETE }}</td>
                    {% endif %}
                </tr>
            {% endfor %}
            </tbody>
        </table>
        <input type="submit" value="{{ _('Submit!') }}" class="button" id="submit-button">
        <a id="add-case-row" href="#"><i class="fa fa-plus"></i> {{ _('Add new case') }}</a>
    </form>
    <div style="display: none" class="generator-args-editor"><textarea></textarea><a class="button">Save</a></div>
{% endblock %}