<template>
    <draggable
        ref="draggable"
        v-model="iVal"
        tag="ul"
        handle=".handle"
        ghost-class="ghost"
        class="list-unstyled"
        item-key="index"
        :group="group"
    >
        <template #item="{ element: { value, index } }">
            <li>
                <div>
                    <div class="input-group input-group-sm mb-1">
                        <button
                            v-if="!disableSorting"
                            :class="['btn', 'btn-light border', readonly ? '' : 'handle']"
                            type="button"
                            :aria-label="$t('table.sort')"
                            :disabled="readonly"
                        >
                            <Icon v="bars" />
                        </button>
                        <slot :val="value" :update="curry(update)(index)" :i="index">
                            <input
                                :value="value"
                                type="text"
                                class="form-control"
                                required
                                :readonly="readonly"
                                :maxlength="maxlength"
                                @input="(event) => update(index, event.target.value)"
                            >
                        </slot>
                        <button
                            v-if="index >= minitems"
                            :class="['btn', readonly ? 'btn-light border' : 'btn-outline-danger']"
                            type="button"
                            :aria-label="$t('crud.remove')"
                            :disabled="readonly"
                            @click.prevent="remove(index)"
                        >
                            <Icon v="times" />
                        </button>
                    </div>
                    <slot name="validation" :val="value" :i="index"></slot>
                </div>
            </li>
        </template>
        <template #footer>
            <li>
                <button
                    v-if="!readonly && (maxitems === null || iVal.length < maxitems)"
                    class="btn btn-outline-success w-100 btn-sm"
                    type="button"
                    :aria-label="$t('crud.add')"
                    @click.prevent="add"
                >
                    <Icon v="plus" />
                </button>
            </li>
        </template>
        <li v-if="maxitems && iVal.length > maxitems" class="alert alert-danger">
            <Icon v="exclamation-triangle" />
            <T :params="{ maxlength: maxitems }" class="ml-1">crud.validation.listMaxLength</T>
        </li>
    </draggable>
</template>

<script>
import draggable from 'vuedraggable';

import { curry } from '../src/helpers.ts';

export default {
    components: {
        draggable,
    },
    props: {
        modelValue: {},
        prototype: { default: '', type: [String, Object] },
        group: {},
        readonly: { type: Boolean },
        maxlength: { default: 32, type: Number },
        minitems: { default: 0, type: Number },
        maxitems: { default: null, type: Number },
        disableSorting: { type: Boolean },
    },
    emits: ['update:modelValue'],
    data() {
        return {
            curry,
        };
    },
    computed: {
        iVal: {
            get() {
                return this.modelValue.map((value, index) => ({ value, index }));
            },
            set(iVal) {
                this.$emit('update:modelValue', iVal.map(({ value }) => value));
            },
        },
    },
    methods: {
        remove(i) {
            const v = [...this.modelValue];
            v.splice(i, 1);
            this.$emit('update:modelValue', v);
        },
        add() {
            // create a deep copy of the prototype
            const addedItem = JSON.parse(JSON.stringify(this.prototype));
            this.$emit('update:modelValue', [...this.modelValue, addedItem]);
            this.$nextTick((_) => {
                const items = this.$refs.draggable.$el.querySelectorAll('[data-draggable]');
                items[items.length - 1].querySelector('input,textarea,select').focus();
            });
        },
        update(i, val) {
            const v = [...this.modelValue];
            v[i] = val;
            this.$emit('update:modelValue', v);
        },
    },
};
</script>

<style lang="scss" scoped>
    .ghost {
        opacity: 0.5;
        background: #c8ebfb;
    }
</style>
