<template>
    <!-- <input
            v-model="data.search"
            @change="onChange"
            type="text"
            class="text-base font-medium block w-full rounded-md border transition ease-in-out focus:ring-1 border-gray-300 border-solid py-2 px-3 text-gray-700 placeholder-gray-400 focus:border-blue-200 focus:ring-blue-500 focus:outline-none"
            v-bind:name="props.name"
        />
        <ul v-if="data.isOpen" class="mt-1 border-2 border-slate-50 overflow-auto shadow-lg rounded list-none">
            <li
                :class="['hover:bg-blue-100 hover:text-blue-800', 'w-full list-none text-left py-2 px-3 cursor-pointer']"
                v-for="(result, i) in data.results"
                :key="i"
            >
                {{ result.name }}
            </li>
        </ul> -->

    <!-- <div class="flex-col justify-center relative"> -->
    <div class="mb-6 mx-2 mt-2">
        <div class="relative">
            <input
                v-model="data.search"
                type="text"
                :class="inputElClass"
                :name="props.name"
                :placeholder="placeholder"
                autocomplete="off"
                @keydown.down="onArrowDown"
                @keydown.up="onArrowUp"
                @keydown.enter="onEnter"
            />
            <svg
                class="w-4 h-4 absolute left-2.5 top-3.5"
                xmlns="http://www.w3.org/2000/svg"
                fill="none"
                viewBox="0 0 24 24"
                stroke="currentColor"
            >
                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
            </svg>
        </div>
        <!-- <ul v-if="data.isOpen" class="bg-white border border-gray-100 w-full mt-2 max-h-28 overflow-y-auto"> -->
        <!-- :ref="(el) => { ul[i] = el }" -->
        <ul v-if="data.isOpen" class="bg-white dark:bg-slate-800 w-full mt-2 max-h-28 overflow-y-auto scroll-smooth">
            <li
                class="pl-8 pr-2 py-1 border-b-2 border-gray-100 relative cursor-pointer hover:bg-yellow-50 hover:text-gray-900"
                :class="{
                    'bg-yellow-50 text-gray-900': i == selectedIndex,
                }"
                v-for="(result, i) in data.results"
                :key="i"
                @click.prevent="setResult(result)"
                :ref="
                (el: HTMLLIElement) => {
                    ul[i] = el;
                }
            "
            >
                <svg class="absolute w-4 h-4 left-2 top-2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor">
                    <path
                        fill-rule="evenodd"
                        d="M12.293 5.293a1 1 0 011.414 0l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414-1.414L14.586 11H3a1 1 0 110-2h11.586l-2.293-2.293a1 1 0 010-1.414z"
                        clip-rule="evenodd"
                    />
                </svg>
                <!-- <b>Gar</b>{{ result.name }} -->

                <!-- <span>
               {{  makeBold(result.name) }}
            </span> -->
                <span
                    v-for="(item, index) in makeBold(result.name)"
                    :key="index"
                    :class="{
                        'font-bold': data.search.toLowerCase().includes(item.toLowerCase()),
                        'is-active': index == selectedIndex,
                    }"
                >
                    {{ item }}
                </span>
                <span> - {{ result.email }}</span>
            </li>
        </ul>
    </div>
</template>

<script setup lang="ts">
import { reactive, ref, computed, Ref, watch } from 'vue';
import axios from 'axios';
let props = defineProps({
    name: {
        type: String,
        required: false,
        default: 'autocomplete',
    },
    source: {
        type: [String, Array, Function],
        required: true,
        default: '',
    },
    label: {
        type: String,
        required: false,
        default: 'name',
    },
    responseProperty: {
        type: String,
        required: false,
        default: 'name',
    },
    placeholder: {
        type: String,
        default: null,
    },
    icon: {
        type: String,
        default: null,
    },
    required: Boolean,
    borderless: Boolean,
    transparent: Boolean,
    ctrlKFocus: Boolean,
});

const emit = defineEmits(['person']);

const inputElClass = computed(() => {
    const base = [
        'px-3 py-2 max-w-full focus:ring focus:outline-none border-gray-700 rounded w-full',
        'dark:placeholder-gray-400',
        'h-12',
        props.borderless ? 'border-0' : 'border',
        props.transparent ? 'bg-transparent' : 'bg-white dark:bg-slate-800',
        // props.isReadOnly ? 'bg-gray-50 dark:bg-slate-600' : 'bg-white dark:bg-slate-800',
    ];
    // if (props.icon) {
    base.push('pl-10');
    // }
    return base;
});

let search = ref('');
let data = reactive({
    search: search,
    isOpen: false,
    results: [] as Array<any>,
});
let error = ref('');
let selectedIndex: Ref<number> = ref(0);
// const listItem = ref(null);
const ul: Ref<Array<HTMLLIElement>> = ref([]);

watch(selectedIndex, (selectedIndex: number) => {
    if (selectedIndex != null && ul.value != null) {
        const currentElement: HTMLLIElement = ul.value[selectedIndex];
        currentElement &&
            currentElement.scrollIntoView({
                behavior: 'smooth',
                block: 'nearest',
                inline: 'start',
            });
    }
});

watch(search, async () => {
    await onChange();
});


// function onChange() {
//     if (!props.source || !data.search) {
//         return false;
//     }

//     data.isOpen = true;
//     arrayLikeSearch(props.source);
// }
async function onChange() {
    if (!props.source || !data.search) return false;

    selectedIndex.value = 0;

    if (data.search.length >= 2) {
        data.isOpen = true;
        switch (true) {
            case typeof props.source === 'string':
                return await request(props.source, data.search);
            // case typeof props.source === 'function':
            //     return props.source(data.search).then((response) => {
            //         data.results = getResults(response);
            //     });
            case Array.isArray(props.source):
                return arrayLikeSearch(props.source);
            default:
                throw new Error('typeof source is ' + typeof props.source);
        }
    } else {
        data.results = [];
        data.isOpen = false;
    }
}

function getResults(response) {
    // if (props.responseProperty) {
    //     let foundObj;
    //     JSON.stringify(response, (_, nestedValue) => {
    //         if (nestedValue && nestedValue[props.responseProperty]) foundObj = nestedValue[props.responseProperty];

    //         return nestedValue;
    //     });
    //     return foundObj;
    // }
    if (Array.isArray(response)) {
        return response;
    }
    return [];
}

// function setResult(result) {
//     data.search = result[props.label];
//     data.isOpen = false;
// }

// function request(url) {
//     return axios.get(url).then((response) => {
//         data.results = getResults(response);
//     });
// }
async function request(url, param) {
    try {
        let response = await searchTerm(url, param);
        error.value = '';
        data.results = getResults(response);
        // this.results = res.data;
        // this.loading = false;
    } catch (error) {
        error.value = error.message;
        // this.loading = false;
    }
}

async function searchTerm(term: string, param): Promise<any> {
    let res = await axios.get(term, { params: { filter: param } });
    // console.log(res.data);
    return res.data; //.response;//.docs;
}
// async function request(term: string): Promise<any> {
//     let res = await axios.get('/api/persons', { params: { filter: term } });
//     return res.data; //.response;//.docs;
// }

function arrayLikeSearch(items) {
    data.results = items.filter((item) => {
        return item.toLowerCase().indexOf(data.search.toLowerCase()) > -1;
    });
}

function makeBold(suggestion) {
    const query = data.search.valueOf();
    const regex = new RegExp(query.split('').join('-?'), 'i');
    const test = suggestion.replace(regex, (match) => '<split>' + match + '<split>');
    // return suggestion.match(regex);
    // const splitWord = suggestion.match(regex);
    return test.split('<split>');
}

function onArrowDown() {
    if (data.results.length > 0) {
        selectedIndex.value = selectedIndex.value === data.results.length - 1 ? 0 : selectedIndex.value + 1;
        // const currentElement: HTMLLIElement = ul.value[selectedIndex.value];
    }
}

function onArrowUp() {
    if (data.results.length > 0) {
        selectedIndex.value = selectedIndex.value == 0 || selectedIndex.value == -1 ? data.results.length - 1 : selectedIndex.value - 1;
    }
}

function setResult(person) {
    // this.search = person.full_name;
    clear();
    // this.$emit('person', person);
    emit('person', person);
}

function clear() {
    data.search = '';
    data.isOpen = false;
    data.results = [];
    error.value = '';
    // this.$emit("clear");
}

function onEnter() {
    if (Array.isArray(data.results) && data.results.length && selectedIndex.value !== -1 && selectedIndex.value < data.results.length) {
        //this.display = this.results[this.selectedIndex];
        const person = data.results[selectedIndex.value];
        // this.$emit('person', person);
        emit('person', person);
        clear();
        selectedIndex.value = -1;
    }
}
</script>
