<template>
    <div>
        <draggable
            v-model="iVal"
            tag="ul"
            ghost-class="ghost"
            :group="ulid"
            class="list-inline border rounded drop-empty px-3 py-2"
            @end="$emit('input', iVal)"
        >
            <template v-for="val in iVal">
                <li v-if="options[val]" :key="val" class="list-inline-item py-1">
                    <a
                        href="#"
                        class="badge bg-light text-dark border p-2"
                        @click.prevent="$emit('input', iVal.filter(v => v !== val))"
                    >
                        <slot :v="val" :desc="options[val]">
                            {{ val }}
                        </slot>
                        <span class="text-danger">
                            <Icon v="times" />
                        </span>
                    </a>
                </li>
            </template>
        </draggable>
        <div class="input-group py-1">
            <input v-model="search" class="form-control" :placeholder="$t('crud.search')">
            <button v-if="search" type="button" class="btn btn-light btn-sm border text-danger" @click.prevent="search = ''">
                <Icon v="times" />
            </button>

            <button v-if="all" type="button" class="btn btn-light btn-sm border" @click.prevent="all = false">
                <Icon v="caret-up" />
            </button>
            <button v-else type="button" class="btn btn-light btn-sm border" @click.prevent="all = true">
                <Icon v="caret-down" />
            </button>
        </div>

        <draggable
            v-model="remainingOptions"
            tag="ul"
            ghost-class="ghost"
            class="list-inline"
            :group="ulid"
            @end="$emit('input', iVal)"
        >
            <li v-for="val in visibleRemainingOptions" :key="val" class="list-inline-item py-1">
                <a href="#" class="badge bg-light text-dark p-2" @click.prevent="$emit('input', [...iVal, val])">
                    <slot :v="val" :desc="options[val]">
                        {{ val }}
                    </slot>
                    <span class="text-success">
                        <Icon v="plus" />
                    </span>
                </a>
            </li>
        </draggable>
    </div>
</template>

<script lang="ts">
import type { PropType } from 'vue';
import Vue from 'vue';
import draggable from 'vuedraggable';
import { ulid } from 'ulid';

export default Vue.extend({
    components: {
        draggable,
    },
    props: {
        value: { required: true, type: Array as PropType<string[]> },
        options: { required: true, type: Object as PropType<Record<string, string>> },
    },
    data() {
        return {
            iVal: this.value,
            remainingOptions: [] as string[],
            ulid: ulid(),
            search: '',
            all: false,
        };
    },
    computed: {
        visibleRemainingOptions(): string[] {
            if (this.search) {
                return this.remainingOptions.filter((val) => {
                    return this.options[val].toLowerCase().includes(this.search.toLowerCase());
                });
            } else if (this.all) {
                return this.remainingOptions;
            } else {
                return [];
            }
        },
    },
    watch: {
        value() {
            this.iVal = this.value;
            this.remainingOptions = this.buildRemainingOptions();
            this.search = '';
        },
    },
    created() {
        this.remainingOptions = this.buildRemainingOptions();
    },
    methods: {
        buildRemainingOptions(): string[] {
            return Object.keys(this.options).filter((o) => !this.value.includes(o));
        },
    },
});
</script>


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

    .drop-empty:empty {
        min-height: 3em;
    }
</style>
