<template>
    <div>
        <input type="hidden" :name="_prefix + 'TOTAL_FORMS'" :value="items.length || 0"/>
        <template v-for="(value,name) in formData.management" v-bind:key="name">
            <input type="hidden" :name="_prefix + name.toUpperCase()"
                :value="value"/>
        </template>

        <a-rows ref="rows" :set="set"
                :columns="visibleFields" :columnsOrderable="columnsOrderable"
                :orderable="orderable" @move="moveItem" @colmove="onColumnMove"
                @cell="e => $emit('cell', e)">

            <template #header-head>
                <template v-if="orderable">
                    <th style="max-width:2em" :title="orderField.label"
                            :aria-label="orderField.label"
                            :aria-description="orderField.help || ''">
                        <span class="icon">
                            <i class="fa fa-arrow-down-1-9"></i>
                        </span>
                    </th>
                    <slot name="rows-header-head"></slot>
                </template>
            </template>

            <template #row-head="data">
                <input v-if="orderable" type="hidden"
                    :name="_prefix + data.row + '-' + orderBy"
                    :value="data.row"/>
                <input type="hidden" :name="_prefix + data.row + '-id'"
                    :value="data.item ? data.item.id : ''"/>

                <template v-for="field of hiddenFields" v-bind:key="field.name">
                    <input type="hidden"
                        v-if="!(field.name in ['id', orderBy])"
                        :name="_prefix + data.row + '-' + field.name"
                        :value="field.value in [null, undefined] ? data.item.data[name] : field.value"/>
                </template>

                <slot name="row-head" v-bind="data">
                    <td v-if="orderable">{{ data.row+1 }}</td>
                </slot>
            </template>

            <template v-for="(field,slot) of fieldSlots" v-bind:key="field.name"
                    v-slot:[slot]="data">
                <slot :name="slot" v-bind="data" :field="field" :input-name="_prefix + data.cell.row + '-' + field.name">
                    <div class="field">
                        <div class="control">
                            <slot :name="'control-' + field.name" v-bind="data" :field="field" :input-name="_prefix + data.cell.row + '-' + field.name"/>
                        </div>
                        <p v-for="[error,index] in data.item.error(field.name)" class="help is-danger" v-bind:key="index">
                            {{ error }}
                        </p>
                    </div>
                </slot>
            </template>

            <template #row-tail="data">
                <slot v-if="$slots['row-tail']" name="row-tail" v-bind="data"/>
                <td class="align-right pr-0">
                    <button type="button" class="button square"
                            @click.stop="removeItem(data.row, data.item)"
                            :title="labels.remove_item"
                            :aria-label="labels.remove_item">
                        <span class="icon"><i class="fa fa-trash" /></span>
                    </button>
                </td>
            </template>
        </a-rows>
        <div class="a-formset-footer flex-row">
            <div class="flex-grow-1 flex-row">
                <slot name="footer"/>
            </div>
            <div class="flex-grow-1 align-right">
                <button type="button" class="button square is-warning p-2"
                        @click="reset()"
                        :title="labels.discard_changes"
                        :aria-label="labels.discard_changes"
                        >
                    <span class="icon"><i class="fa fa-rotate" /></span>
                </button>
                <button type="button" class="button square is-primary p-2"
                        @click="onActionAdd"
                        :title="labels.add_item"
                        :aria-label="labels.add_item"
                        >
                    <span class="icon">
                        <i class="fa fa-plus"/></span>
                </button>
            </div>
        </div>
    </div>
</template>
<script>
    import {cloneDeep} from 'lodash'
    import Model, {Set} from '../model'

    import ARows from './ARows'

    export default {
        emit: ['cell', 'move', 'colmove', 'load'],
        components: {ARows},

        props: {
            labels: Object,

            //! If provided call this function instead of adding an item to rows on "+" button click.
            actionAdd: Function,

            //! If True, columns can be reordered
            columnsOrderable: Boolean,
            //! Field name used for ordering
            orderBy: String,

            //! Formset data as returned by get_formset_data
            formData: Object,
            //! Model class used for item's set
            model: {type: Function, default: Model},
            //! initial data set load at mount
            initials: Array,
        },

        data() {
            return {
                set: new Set(Model),
            }
        },

        computed: {
            // ---- fields
            _prefix() { return this.formData.prefix ? this.formData.prefix + '-' : '' },
            fields() { return this.formData.fields },
            orderField() { return this.orderBy && this.fields.find(f => f.name == this.orderBy) },
            orderable() { return !!this.orderField },

            hiddenFields() { return this.fields.filter(f => f.hidden && !(this.orderable && f == this.orderField)) },
            visibleFields() { return this.fields.filter(f => !f.hidden) },

            fieldSlots() { return this.visibleFields.reduce(
                (slots, f) => ({...slots, ['row-' + f.name]: f}),
                {}
            )},

            items() { return this.set.items },
            rows() { return this.$refs.rows },
        },

        methods: {
            onCellEvent(event) { this.$emit('cell', event) },
            onColumnMove(event) { this.$emit('colmove', event) },
            onActionAdd() {
                if(this.actionAdd)
                    return this.actionAdd(this)
                this.set.push()
            },

            moveItem(event) {
                const {from, to} = event
                const set_ = event.set || this.set
                set_.move(from, to);
                this.$emit('move', {...event, seŧ: set_})
            },

            removeItem(row) {
                const item = this.items[row]
                if(item.id) {
                    // TODO
                }
                else {
                    this.items.splice(row,1)
                }
            },

            //! Load items into set
            load(items=[], reset=false) {
                if(reset)
                    this.set.items = []
                for(var item of items)
                    this.set.push(cloneDeep(item))
                this.$emit('load', items)
            },

            //! Reset forms to initials
            reset() {
                this.load(this.initials || [], true)
            },
        },

        mounted() {
            this.reset()
        }
    }
</script>
