<template>
    <div>
        <div
            class="bs-font-medium-2-normal"
            v-if="label"
            style="padding-bottom: 4px"
        >
            {{ label }}
        </div>
        <div :style="{ 'max-width': '300px' }" class="bs-selection-content">
            <BsSelect
                v-model="selectedVariables"
                :options="options"
                clear-icon="clear"
                multiple
                dense
                use-chips
                @filter="filterFn"
                use-input
                input-debounce="0"
                :disable="disabled"
            >
                <!-- Templates for selected item and options -->
                <template #selected-item></template>
                <template #option="props">
                    <q-item
                        v-if="props.index === 0"
                        clickable
                        @click="toggleAll"
                        class="bs-font-medium-2-normal bs-selector-dropdown-item"
                        style="padding: 8px"
                    >
                        <q-item-section side>
                            <q-checkbox
                                :model-value="allSelected"
                                @update:model-value="toggleAll"
                                :indeterminate="isSomeSelected"
                                size="24px"
                            ></q-checkbox>
                        </q-item-section>
                        <q-item-section> Select All </q-item-section>
                    </q-item>

                    <q-item
                        padding="0"
                        v-bind="props.itemProps"
                        clickable
                        class="bs-font-medium-2-normal bs-selector-dropdown-item"
                    >
                        <q-item-section side>
                            <q-checkbox
                                size="24px"
                                :model-value="props.selected"
                                @update:model-value="
                                    props.toggleOption(props.opt)
                                "
                            ></q-checkbox>
                        </q-item-section>
                        <q-item-section>
                            <BSTruncatedText :tooltip-content="props.opt">
                                {{ props.opt }}</BSTruncatedText
                            >
                        </q-item-section>
                    </q-item>
                </template>
            </BsSelect>

            <BsWarning v-if="showWarning" :text="warningText"></BsWarning>

            <div>
                <div
                    class="bs-selected-items-section"
                    v-if="selectedVariables && selectedVariables.length > 0"
                >
                    <!-- Selected Items Display -->
                    <div class="bs-selected-items-container">
                        <div
                            v-if="!showAllSelected"
                            v-for="(item, index) in displayedItems"
                            :key="index"
                            class="bs-font-small-2-normal bs-selected-item"
                        >
                            <div>{{ item }}</div>
                            <BsIcon
                                name="close"
                                @click="deleteItem(item)"
                            ></BsIcon>
                        </div>

                        <div
                            v-if="showAllSelected"
                            class="bs-selected-items-container bs-all-selected"
                        >
                            <div
                                v-for="item in selectedVariables"
                                :key="item"
                                class="bs-font-small-2-normal bs-selected-item"
                            >
                                {{ item }}
                                <BsIcon
                                    name="close"
                                    @click="deleteItem(item)"
                                ></BsIcon>
                            </div>
                        </div>
                    </div>
                    <BsButton
                        class="bs-font-medium-1-normal-underline bs-clear-all"
                        unelevated
                        flat
                        no-caps
                        padding="4"
                        @click="clearAllSelection"
                    >
                        Clear All
                    </BsButton>
                </div>
                <div
                    class="bs-font-medium-1-normal bs-view-more"
                    v-if="selectedVariables.length > 4"
                    @click="showAllSelected = !showAllSelected"
                >
                    View {{ selectedVariables.length - 4 }}
                    {{ showAllSelected ? "less" : "more" }}
                    <BsIcon
                        :name="!showAllSelected ? mdiChevronDown : mdiChevronUp"
                    ></BsIcon>
                </div>
            </div>
        </div>
    </div>
</template>

<script lang="ts">
import { defineComponent } from "vue";
import { BsIcon, BsSelect } from "quasar-ui-bs";
import { mdiChevronDown, mdiChevronUp } from "@quasar/extras/mdi-v6";
import BSTruncatedText from "./BsTruncatedText.vue";
import BsWarning from "./BsWarning.vue";
import { isEqual } from "lodash";
export default defineComponent({
    name: "BSMultiSelect",
    components: {
        BsSelect,
        BsWarning,
        BsIcon,
        BSTruncatedText,
    },
    props: {
        disabled: Boolean,
        allOptions: {
            type: Array<string>,
            required: true,
        },
        modelValue: {
            type: Array<string>,
            default: () => [],
        },
        showWarning: {
            type: Boolean,
            default: false,
        },
        warningText: {
            type: String,
            default: "",
        },
        label: {
            type: String,
            default: "",
        },
    },
    emits: ["update:modelValue"],
    data() {
        return {
            mdiChevronDown,
            mdiChevronUp,
            selectedVariables: [] as string[],
            options: [] as string[],
            showAllSelected: false,
            selectAllChecked: false,
        };
    },
    watch: {
        "selectedVariables.length"() {
            this.$emit("update:modelValue", this.selectedVariables);
        },
        selectedVariables(newVal, oldVal) {
            if (!isEqual(newVal, oldVal)) {
                this.$emit("update:modelValue", this.selectedVariables);
            }
        },
        modelValue(newValue) {
            this.selectedVariables = newValue;
        },
    },
    mounted() {
        this.selectedVariables = this.modelValue;
    },
    computed: {
        displayedItems(): string[] {
            return this.selectedVariables.slice(0, 4);
        },
        allSelected(): boolean {
            const countSelected = this.selectedVariables.reduce(
                (prev, curr) => {
                    if (this.options.indexOf(curr) >= 0) {
                        return prev + 1;
                    } else {
                        return prev;
                    }
                },
                0
            );
            return countSelected === this.options.length;
        },
        isSomeSelected(): boolean {
            return this.selectedVariables.length > 0 && !this.allSelected;
        },
    },
    methods: {
        filterFn(val: string, update: any) {
            update(() => {
                const needle = val.toLowerCase();
                this.options = this.allOptions.filter(
                    (v) => v.toLowerCase().indexOf(needle) > -1
                );
            });
        },
        clearAllSelection() {
            this.selectedVariables = [];
        },
        deleteItem(itemToDelete: string) {
            this.selectedVariables = this.selectedVariables.filter(
                (item) => item !== itemToDelete
            );
        },
        toggleAll() {
            if (this.allSelected) {
                this.selectedVariables = this.selectedVariables.filter(
                    (el) => this.options.indexOf(el) === -1
                );
            } else {
                this.options.forEach((option) => {
                    if (this.selectedVariables.indexOf(option) === -1) {
                        this.selectedVariables.push(option);
                    }
                });
            }
        },
    },
});
</script>

<style scoped>
.bs-selected-items-section {
    display: flex;
    align-items: stretch;
}
.bs-selected-items-container {
    display: flex;
    flex-wrap: wrap;
    gap: var(--bs-spacing-1, 4px);
    align-items: center;
    width: 100%;
    border-right: solid 1px var(--base-colors-bs-color-border-light, #e5e5e5);
    max-height: 500px;
    overflow-y: scroll;
}

.bs-selected-item {
    color: var(--text-and-icons-bs-color-text-with-background, #fff) !important;
    display: flex;
    padding: var(--bs-spacing-0, 0px) var(--bs-spacing-1, 4px);
    justify-content: center;
    align-items: center;
    gap: var(--bs-spacing-1, 4px);
    border-radius: 4px;
    background: var(--interactions-bs-color-interaction-selected, #214ab5);
}
.bs-view-more {
    color: var(--text-and-icons-bs-color-text, #333e48);
    display: block;
    margin-top: 8px;
}
.bs-clear-all {
    width: 53px;
    margin-left: auto;
    padding: var(--bs-spacing-0, 0px) var(--bs-spacing-1, 4px);
    align-self: center;
    color: var(--text-and-icons-bs-color-text, #333e48);
}

.all-selected {
    flex-wrap: wrap;
    overflow-y: auto;
    max-height: 100px;
    padding-bottom: 10px;
}
.bs-selection-content {
    display: flex;
    flex-direction: column;
    gap: 10px;
}
</style>
<style>
.bs-select__popup {
    max-height: 500px !important;
    overflow-y: scroll;
    transition: max-height 0.5s;
}
</style>
