<template>
    <div class="text-start otherSelect" :class="formClass">
        <label class=" fw-bold rounded text-dark bg-white " :class="labelClass">{{ label }}</label><br>
        <div class="input-group mb-3 border-black border-1">
            <input type="text" class="form-control " :class="inputClass" :placeholder="placeholder" @change="active=true" 
                @focus="active=true" v-model="search" :readonly="readOnly" :disabled="disabled">
                <i class="bi bi-list bg-secondary bg-gradient text-light input-group-text" @click.prevent="active=!active"></i>
            <!-- <div class="input-group-append text-dark">
            </div> -->
        </div>
        <div v-if="multiMode" class="text-muted">
            <div >
                <p class="text-muted " >
                    <span class="badge bg-primary m-1 p-0 selected-badge " v-for="sel,i in selected" :key="i">
                        <text class="px-1">{{ showMultiSelect(sel) }} </text>
                        <button class="btn-close btn-sm mx-1 p-1" aria-label="Close" @click.prevent="selected.splice(i,1)"></button>
                    </span>
                </p>
            </div>
        </div>
        <p v-else >
            <span class="badge bg-primary " v-if="selected!=null" >{{ showSingleSelect }}</span>
        </p>
        <i class="btn btn-sm btn-primary" v-if="addNew && search.length>0" @click.prevent="addNewEntry()">Add '{{ search }}'</i>
        <ul class="list-group list-group w-100 z-3 overflow-y-auto" :class="listClass[active]" >
            <li class="list-group-item" v-for="opt,i in filterOptions" :key="i" @click.prevent="select(opt)" :tabindex="i+1">{{ showMultiSelect(opt) }}</li>
        </ul>
        <!-- <ul class="list-group list-group w-100 position-absolute top-100 start-0 shadow shadow-1 bg-warning z-3 overflow-y-auto" :class="listClass[active]" >
            <li class="list-group-item" v-for="opt,i in filterOptions" :key="i" @click.prevent="select(opt)" :tabindex="i+1">{{ showMultiSelect(opt) }}</li>
        </ul> -->
    </div>    
</template>
<script>

export default {
    name: 'otherSelect',
    props: {
        modelValue:[String,Object,Array],
        options: {
            type: Array,
            default: () => []
        },
        selectedDefault: {
            type: [String, Object, Array],
            default: null
        },
        multiMode: {
            type: Boolean,
            default: false
        },
        objectMode: {
            type: Boolean,
            default: false
        },
        addNew: {
            type: Boolean,
            default: false
        },
        dispVal: {
            type: String,
            default: 'name'
        },
        objKey: {
            type: String,
            default: 'id'
        },
        placeholder:{ type:String, default:"Search for options..." },
        inputClass:{ type:String, default:" "},
        labelClass:{ type:String, default:" "},
        label:{ type:[String,Number], default:"Select a Value"},
        readonly:{type:Boolean,default:false},
        disabled:{type:Boolean,default:false},
        formClass:{type:String,default:""},
        readOnly:{type:Boolean,default:false}
    },
    data() {
        return {
            selected: this.selectedDefault,
            search: '',
            listClass:{
                false: 'd-none',
                true: 'd-block'
            },
            active: false,
        }
    },
    watch: {
        selected(newVal) {
            this.selected = newVal;
        }
    },
    computed: {
        filterOptions(){
            try {
                return this.selected==null? this.optionsFilterSearch(this.options) : this.optionsFilterSearch(this.optionsFilterSelected(this.options));
                
            } catch (error) {
                console.log(error);
                return this.objectMode? [{[this.objKey]:-1,[this.dispVal]:"[UI Error: check objectMode and multiMode props]"}] : ['[UI Error: check objectMode and multiMode props]']
            }
        },        
        showSingleSelect() {
            return this.objectMode? this.selected[this.dispVal] : this.selected;
        }
    },
    methods: {
        optionsFilterSearch(options){
            console.log(`Object Mode: ${this.objectMode}`)
            return options.filter(opt => {
                        return this.objectMode? 
                                        opt[this.dispVal].toLowerCase().includes(this.search ? this.search.toLowerCase() : '')
                                        : 
                                        opt.toLowerCase().includes(this.search ? this.search.toLowerCase() : '')
                       
                    });            
        },
        optionsFilterSelected(options){
            return options.filter(opt => {
                        return this.multiMode? 
                                        this.objectMode? 
                                            !this.selected.find(o=> o[this.objKey]===opt[this.objKey] && o[this.dispVal]===opt[this.dispVal] ) 
                                            : 
                                            !this.selected.includes(opt)
                                        : 
                                        this.objectMode? 
                                            JSON.stringify(this.selected)!=JSON.stringify(opt)
                                            : 
                                            this.selected!=opt
                       
                    });
        },
        updateSelected() {
            this.$emit('update:modelValue', this.selected);
        },
        select(opt) {
            this.multiMode? this.selected.push(opt) : this.selected = opt;
            this.multiMode? null :this.active=false ;
            this.search = '';
            this.updateSelected();
        },
        addNewEntry() {
            //is it multiple options mode?
            this.multiMode? 
                        //if multiMode YES, then is it in object mode?
                        this.objectMode? //is it the option a JSON object?

                            this.selected.push({[this.objKey]: this.search, [this.dispVal]: this.search}) 
                            : 
                            this.selected.push(this.search)
                        :
                        //if multiMode NO, then is it in object mode?
                        this.objectMode? //is it the option a JSON object?
                            this.selected={[this.objKey]:this.search, [this.dispVal]: this.search} 
                            :
                            this.selected = this.search;
            this.search = '';
            this.updateSelected();            
        },
        showMultiSelect(opt) {
            return this.objectMode? opt[this.dispVal] : opt;
        },
    },
    mounted() {
        if (this.selectedDefault==null) {
                this.multiMode? 
                    this.selected = [] 
                    : 
                    this.selected = null;
            }
        else{

            typeof(this.selectedDefault)=='string'? this.selected = {[this.objKey]: this.selectedDefault, [this.dispVal]:this.selectedDefault} : this.selected = this.selectedDefault;          
        }
        
        this.$emit('update:modelValue', this.selected);        
    },
}
</script>
<style scoped>
    .list-group-item:nth-child(odd) {
      background-color: #f8f9fa;
    }
    .list-group-item:hover {
      background-color: #e9ecef;
    }
    .list-group-item {
      cursor: pointer;
    }
    .selected-badge {
        font-size: medium;
    }
    .btn-close {
        cursor: pointer;
    }
    .btn-close:hover {
        color: red;
    }
    label{
        z-index: 2;
        padding: .1rem .75rem;
        overflow: hidden;
        text-align: start;
        text-overflow: ellipsis;
        white-space: nowrap;
        pointer-events: none;
        border: var(--bs-border-width) solid transparent;
        transform-origin: 0 0;
        transition: opacity .1s ease-in-out, transform .1s ease-in-out;
        transform: scale(.85) translateY(.5rem) translateX(.01rem);
        
    }
    .otherSelect{
        transition: width 2s;
        transition-timing-function: ease-in-out;
    }
  </style>