<script>
    import { t }    from '../translations.svelte.js'
    import { tick } from "svelte";


    let {
        id            = null,
        autofocus     = false,
        getCandidates = dummyGetCandidates,
        onCommit      = dummyOnCommit,
        onSelect      = dummyOnSelect,
        candidate     = $bindable({ display : '' })
    } = $props();

    const ignore   = ['ArrowLeft','ArrowRight'];
    //let candidate  = $state({ display : '' });
    let selected   = $state(null);
    let candidates = $state([]);
    let timer      = null;
    let list_elem;

    async function dummyGetCandidates(text){
        console.warn(`getCandidates(${text}) not overridden!`);
        if (!text) return [];
        return [
            {
                display     : 'candidate 1',
                explanation : 'candidates need to have a display field'
            },
            {
                display    : 'candidate 2',
                additional : 'other fields are optional',
                more       : 'and may be domain specific'
            },
            { display : text }
        ];
    }

    function dummyOnCommit(candidate){
        // if Enter is pressed on the input field, this method gets called with
        // either the selected candidate or
        // an anonymous object with the entered text in the display field
        console.warn(`onCommit(${JSON.stringify(candidate)}) not overridden!`);
        // if the method returns true, the field will be cleared after committing
        return true;
    }

    function dummyOnSelect(candidate){
        console.warn(`${candidate.display} selected, but onSelect not overridden!`)
    }

    function disableDropdown(){
        candidates = [];
        selected = null;
    }

    async function ondblclick(evt){
        const select = evt.target;
        const idx    = select.value;
        candidate = candidates[idx];
        disableDropdown();
        onSelect(candidate);
    }

    async function fetchCandidates(){
        candidates = candidate.display ? await getCandidates(candidate.display) : [];
        selected = null;
    }

    function onblur(ev){
        setTimeout(disableDropdown,400);
    }

    async function onkeyup(ev){
        if (ignore.includes(ev.key)) return;
        if (ev.key == 'ArrowDown'){
            ev.preventDefault();
            selected = selected == null ? 0: selected +1;
            if (selected >= candidates.length) selected = 0;
            scrollTo(selected);
            return false;
        }
        if (ev.key == 'ArrowUp'){
            ev.preventDefault();
            selected = selected == null ? candidates.length -1 : selected -1;
            if (selected < 0) selected = candidates.length -1;
            scrollTo(selected);
            return false;
        }
        if (ev.key == 'Enter'|| ev.key == 'Tab'){
            ev.preventDefault();
            if (selected != null && selected < candidates.length) {
                candidate = candidates[selected];
                disableDropdown();
                onSelect(candidate);
                return false;
            }
            if (ev.key == 'Enter') {
                disableDropdown();
                if (onCommit(candidate)) candidate = { display : '' };
            }
            return false;
        }
        if (ev.key == 'Escape'){
            ev.preventDefault();
            disableDropdown();
            return false;
        }

        candidate = { display : candidate.display };
        if (timer) clearTimeout(timer);
        timer = setTimeout(fetchCandidates,400);
        return false;
    }

    function select(index){
        candidate = candidates[index];
        <disableDropdown></disableDropdown>();
        onSelect(candidate);
    }

    function scrollTo(index){
        let list_elements = list_elem.children;
        if (list_elements) list_elements[index].scrollIntoView({block:'center'});
    }
</script>

<style>
    span { position : relative }
    ul {
        position : absolute;
        top: 30px;
        left: 3px;
        background: black;
        color: orange;
        border: 1px solid orange;
        border-radius: 5px;
        z-index: 65;
        list-style: none;
        padding: 4px;
        margin: 0;
        min-width: 400px;
        max-height: 200px;
        overflow: scroll;
    }
    .highlight { background: orange; color: black; }

</style>

<span class="autocomplete">
    <input type="text" bind:value={candidate.display} {onkeyup} autofocus={autofocus} {id} {onblur} />
    {#if candidates && candidates.length > 0}
    <ul bind:this={list_elem} class="suggestions" tabindex="-1">
        {#each candidates as candidate,i}
        <li class="option {selected==i?'highlight':''}" tabindex="-1" onclick={e => select(i)} ondblclick={e => select(i)}>{candidate.display}</li>
        {/each}
    </ul>
    {/if}
</span>
