<template>
    <div v-if="!multiple || !ordered" class="rule-column-selector">
        <div class="d-flex justify-content-end align-items-center">
            <span v-b-tooltip.hover class="mr-auto help-text" :title="help">{{ label }}</span>
            <div v-b-tooltip.hover class="mr-1" :title="title">
                <SelectBasic :value="target" :multiple="multiple" :options="columnOptions" @input="handleInput" />
            </div>
            <slot></slot>
        </div>
    </div>
    <div v-else class="rule-column-selector">
        <span class="help-text" :title="help">{{ label }}</span>
        <slot></slot>
        <ol>
            <li v-for="(targetEl, index) in target" :key="targetEl" :index="index" class="rule-column-selector-target">
                {{ colHeaders[targetEl] }}
                <span class="fa fa-times rule-column-selector-target-remove" @click="handleRemove(index)"></span>
                <span v-if="index !== 0" class="fa fa-arrow-up rule-column-selector-up" @click="moveUp(index)"></span>
                <span
                    v-if="index < target.length - 1"
                    class="fa fa-arrow-down rule-column-selector-down"
                    @click="moveUp(index + 1)"></span>
            </li>
            <li v-if="target.length < colHeaders.length">
                <span v-if="!orderedEdit" class="rule-column-selector-target-add">
                    <i @click="$emit('update:orderedEdit', true)">... {{ l("Assign Another Column") }}</i>
                </span>
                <span v-else class="rule-column-selector-target-select">
                    <SelectBasic placeholder="Select a column" :options="remainingOptions" @input="handleAdd" />
                </span>
            </li>
        </ol>
    </div>
</template>

<script>
import Vue from "vue";

import _l from "@/utils/localization";

import SelectBasic from "@/components/RuleBuilder/SelectBasic.vue";

export default {
    components: {
        SelectBasic,
    },
    props: {
        target: {
            required: true,
        },
        label: {
            required: false,
            type: String,
            default: _l("From Column"),
        },
        help: {
            required: false,
        },
        colHeaders: {
            type: Array,
            required: true,
        },
        multiple: {
            type: Boolean,
            required: false,
            default: false,
        },
        ordered: {
            type: Boolean,
            required: false,
            default: false,
        },
        valueAsList: {
            type: Boolean,
            required: false,
            default: false,
        },
        orderedEdit: {
            type: Boolean,
            required: false,
            default: false,
        },
    },
    computed: {
        columnOptions() {
            return this.colHeaders.map((col, index) => ({ id: index, text: col }));
        },
        remainingOptions() {
            if (!this.multiple) {
                return this.columnOptions;
            }
            const exclude = new Set(this.target.map(Number));
            return this.columnOptions.filter((opt) => !exclude.has(opt.id));
        },
        title() {
            return _l("Select a column");
        },
    },
    methods: {
        handleInput(value) {
            if (this.multiple) {
                // https://stackoverflow.com/questions/262427/why-does-parseint-yield-nan-with-arraymap
                const val = value.map((idx) => parseInt(idx));
                this.$emit("update:target", val);
            } else {
                let val = parseInt(value);
                if (this.valueAsList) {
                    val = [val];
                }
                this.$emit("update:target", val);
            }
        },
        handleAdd(value) {
            // TODO: Rework add/remove here to not mutate props.
            // eslint-disable-next-line vue/no-mutating-props
            this.target.push(parseInt(value));
            this.$emit("update:orderedEdit", false);
        },
        handleRemove(index) {
            // TODO: See above.
            // eslint-disable-next-line vue/no-mutating-props
            this.target.splice(index, 1);
        },
        moveUp(value) {
            const swapVal = this.target[value - 1];
            Vue.set(this.target, value - 1, this.target[value]);
            Vue.set(this.target, value, swapVal);
        },
    },
};
</script>

<style scoped src="@/components/Help/help-text.scss" />
