<template>
    <div class="w-100">
        <b-input-group v-if="!disabled">
            <template v-slot:prepend>
                <b-button v-if="clearable"
                          size="sm"
                          variant="danger"
                          @click="() => $emit('input', null)">X</b-button>
            </template>
            <j-dropdown v-model="visible"
                        :variant="variant"
                        :size="size"
                        :block="true"
                        class="flex-grow-1">
                <template slot="button">
                    <span v-if="noVal(value)">
                        <slot name="placeholder">{{pch}}</slot>
                    </span>
                    <span v-else>
                        <slot name="result"
                              v-bind:option="value"
                              v-bind:id="getId(value)">
                            {{value}}
                        </slot>
                    </span>
                    &nbsp;
                </template>
                <b-dropdown-header>
                    <input v-model="searchText"
                           class="form-control w-100"
                           ref="txt"
                           :placeholder="pch"
                           @input="typing" />
                </b-dropdown-header>
                <div style="max-height: 200px;position:relative;overflow-y:scroll"
                     class="w-100">
                    <b-dropdown-item-button v-for="item in items"
                                            :key="getId(item)"
                                            @click="onSelect(item)">
                        <slot name="option"
                              v-bind:option="item"
                              v-bind:id="getId(item)">
                        </slot>
                        &nbsp;
                    </b-dropdown-item-button>
                </div>
            </j-dropdown>
        </b-input-group>
        <div v-else>
            <div class="d-flex w-100 align-items-center">
                <div class="flex-grow-1"
                     v-if="noVal(value)">
                    <slot name="placeholder">{{pch}}</slot>
                </div>
                <div class="flex-grow-1"
                     v-else>
                    <slot name="disabled"
                          v-bind:option="value"
                          v-bind:id="getId(value)">
                        <slot name="result"
                              v-bind:option="value"
                              v-bind:id="getId(value)">
                            {{value}}
                        </slot>
                    </slot>
                </div>
            </div>
        </div>
    </div>
</template>

<script>
import { searchObjects } from 'libj-core';
import debounce from "lodash.debounce";
import { i18n } from "../../localization/vue-i18n";
import loc from "./autocomplete.resx";
export default {
    i18n: i18n(loc),
    props: {
        //selected option
        value: {
            default: null
        },
        //get id from item
        getId: {
            default() {
                return o => o;
            }
        },
        serverSide: {
            type: Boolean,
            default: false
        },
        //server side
        getItems: {
            default() {
                return (query, done) => { done([]); };
            }
        },
        //client side
        options: {
            type: Array,
            default() {
                return [];
            }
        },
        //client side
        searchProperties: {
            type: Array,
            default() {
                return [];      //null or empty array means all properties
            }
        },
        placeholder: {
            type: String,
            default: null
        },
        delay: {
            type: Number,
            default: 500
        },
        clearable: {
            type: Boolean,
            default: false
        },
        disabled: {
            type: Boolean,
            default: false
        },
        variant: {
            type: String,
            default: 'primary'
        },
        size: {
            type: String,
            default: null       // null or sm or lg
        },
    },
    data() {
        return {
            visible: false,
            items: [],
            searchText: '',
            pch: '',
            isLoading: false,
            getItemsDelayed: debounce(query => this.searchItems(query), this.delay),
        };
    },
    mounted() {
        this.updatePlaceholder();
    },
    methods: {
        noVal(x) {
            var id = this.getId(x);
            return x === undefined || x === null || x.length === 0 || id === undefined || id === null || id.length === 0;
        },
        show() {
            this.visible = true;
        },
        hide() {
            this.visible = false;
        },
        toggle() {
            this.visible = !this.visible;
        },
        clear() {
            this.$emit('input', null);
        },
        updatePlaceholder() {
            this.pch = this.placeholder === undefined || this.placeholder === null ? this.$t('search') : this.placeholder;
        },
        searchItems(query) {
            this.items.splice(0, this.items.length);
            if (query === undefined || query === null || query.length === 0) {
                this.searchItemsDone([]);
            } else if (this.serverSide) {
                this.isLoading = true;
                this.getItems(query, this.searchItemsDone);
            } else {
                var properties = this.searchProperties === undefined || this.searchProperties === null ||
                    this.searchProperties.length === 0 ? null : this.searchProperties;
                (query, this.options, properties);
                var items = searchObjects(query, this.options, properties);
                this.searchItemsDone(items);
            }
        },
        searchItemsDone(items) {
            this.$emit('searched', items);
            items.forEach(a => this.items.push(a));
            this.isLoading = false;
        },
        setSearchText(text) {
            this.searchText = text;
            this.getItemsDelayed(this.searchText);
        },
        getSearchText() {
            return this.searchText;
        },
        typing() {
            this.$emit('searchTextChanged', this.searchText);
            this.getItemsDelayed(this.searchText);
        },
        onSelect(item) {
            this.items.splice(0, this.items.length);
            this.$emit('input', item);
        },
    },
    watch: {
        visible() {
            if (this.visible) {
                this.searchText = '';
                this.$refs.txt.focus();
            } else {
                this.searchText = '';
            }
        },
        placeholder() {
            this.updatePlaceholder();
        },
        value: {
            handler() {
                this.$emit('change', this.getId(this.value));
            },
            deep: true
        },
    }
}
</script>