<script lang="ts">
 import { tick } from 'svelte'
 import { BlockTitle } from "@gradio/atoms";
 import Select from 'svelte-select';
 // import VirtualList from '$lib/components/VirtualList.svelte';
 import VirtualList from 'svelte-tiny-virtual-list';
 import type { ComfyComboNode } from "$lib/nodes/widgets";
 import { type WidgetLayout } from "$lib/stores/layoutStates";
 import { get, writable, type Writable } from "svelte/store";
 import { isDisabled } from "./utils"
 export let widget: WidgetLayout | null = null;
 export let isMobile: boolean = false;
 let node: ComfyComboNode | null = null;
 let nodeValue: Writable<string> = writable("");
 let propsChanged: Writable<number> | null = null;
 let lightUp: Writable<boolean> = writable(false);
 let valuesForCombo: Writable<any[]> = writable([])
 let lastConfigured: any = null;
 let option: any = null;

 export let debug: boolean = false;
 let input: HTMLInputElement | null = null

 $: widget && setNodeValue(widget);

 $: if (nodeValue !== null) {
     // if (option == null || node.properties.values.indexOf(option.value) === -1) {
     //     setOption($nodeValue)
     //     $nodeValue = option
     // }
     // else {
     //     $nodeValue = option
     //     setOption($nodeValue)
     // }
     setNodeValue(widget)
     node.properties = node.properties
 }

 function setNodeValue(widget: WidgetLayout) {
     if(widget) {
         node = widget.node as ComfyComboNode
         nodeValue = node.value;
         propsChanged = node.propsChanged;
         lightUp = node.lightUp;
         valuesForCombo = node.valuesForCombo;
         lastConfigured = $valuesForCombo
     }
 }

 $: $valuesForCombo != null && updateActiveIndex($valuesForCombo)

 function updateActiveIndex(values: any) {
     const value = $nodeValue;
     activeIndex = values.findIndex(v => v.value === value);
 }

 $: if ($lightUp)
     setTimeout(() => ($lightUp = false), 1000);

 function getLinkValue() {
     if (!node)
         return "???";
     const links = node.getOutputLinks(0)
     if (links.length === 0)
         return "???";
     return links[0].data
 }

 function onFocus() {
     // console.warn("FOCUS")
     if (listOpen) {
         navigator.vibrate(20)
     }
 }

 function onSelect(e: CustomEvent<any>) {
     if (input)
         input.blur();
     navigator.vibrate(20)

     const item = e.detail

     console.debug("[ComboWidget] SELECT", item, item.index)
     $nodeValue = item.value;
     activeIndex = item.index;
     listOpen = false;
 }

 let activeIndex = null;
 let hoverItemIndex = null;
 let filterText = "";
 let listOpen = null;
 let scrollToIndex = null;
 let start = 0;
 let end = 0;

 function handleHover(index: number) {
     // console.warn("HOV", index)
     hoverItemIndex = index;
 }

 function handleSelect(index: number) {
     // console.warn("SEL", index)
     navigator.vibrate(20)
     const item = $valuesForCombo[index]
     activeIndex = index;
     $nodeValue = item.value
     listOpen = false;
     filterText = ""
     input?.blur()
 }

 function onFilter() {
     // if (scrollToIndex)
     //     scrollToIndex(0)
 }

 const activeScroll = scrollAction;
 const hoverScroll = scrollAction;

 function scrollAction(node) {
     return {
         update(args) {
             if (args.scroll) {
                 // handleListScroll();
                 node.scrollIntoView({ behavior: 'auto', block: 'nearest' });
             }
         },
     };
 }

 let title: ""

 $: nodeValue && $nodeValue && (title = getTitle($nodeValue))

 function getTitle(value?: string) {
     if (value == null) {
         if (!nodeValue)
             return ""
         value = $nodeValue
     }

     if (value && value.length > 80)
         return String(value)
     return ""
 }
</script>

<div class="wrapper comfy-combo" class:mobile={isMobile} class:updated={$lightUp}>
    <label title={title}>
        {#if widget.attrs.title !== ""}
            <BlockTitle show_label={true}>
                {widget.attrs.title}
                <span class="count-text">({$valuesForCombo.length})</span>
            </BlockTitle>
        {/if}
        <Select
            value={$valuesForCombo.length === 0 ? "(Loading...)" : $nodeValue}
            bind:justValue={option}
            bind:hoverItemIndex
            bind:filterText
            bind:listOpen
            bind:input
            items={$valuesForCombo}
            disabled={$valuesForCombo.length === 0 || isDisabled(widget)}
            clearable={false}
            showChevron={true}
            listAutoWidth={true}
            inputAttributes={{ autocomplete: 'off' }}
            on:change
            on:focus={onFocus}
            on:hoverItem={(e) => handleHover(e.detail)}
            on:select={(e) => handleSelect(e.detail.index)}
            on:blur
            on:filter={onFilter}>
            <div class="comfy-select-list" slot="list" let:filteredItems style:--maxLabelWidth={node.maxLabelWidthChars || 100}>
                {#if filteredItems.length > 0}
                    {@const itemSize = isMobile ? 50 : 25}
                    {@const itemsToShow = isMobile ? 10 : 30}
                    <VirtualList
                        items={filteredItems}
                        width="100%"
                        height={Math.min(filteredItems.length, itemsToShow) * itemSize}
                        itemCount={filteredItems.length}
                        {itemSize}
                        overscanCount={5}
                        scrollToIndex={hoverItemIndex}>
                        <div slot="item"
                                class="comfy-select-item"
                                class:mobile={isMobile}
                                let:index={i}
                                let:style
                                title={getTitle(filteredItems[i].label)}
                                {style}
                                class:active={activeIndex === filteredItems[i].index}
                                class:hover={hoverItemIndex === i}
                                on:click={() => handleSelect(filteredItems[i].index)}
                            on:focus={() => handleHover(i)}
                            on:mouseover={() => handleHover(i)}>
                            {@const item = filteredItems[i]}
                            <span class="comfy-select-label">
                                {item.label}
                            </span>
                        </div>
                    </VirtualList>
                {:else}
                    <div class="comfy-empty-list">
                        <span>(No items)</span>
                    </div>
                {/if}
            </div>
        </Select>
    </label>
</div>

<style lang="scss">
 .wrapper {
     padding: 2px;
     width: 100%;

     .count-text {
         font-size: smaller;
     }

     :global(.selected-item) {
         // no idea how to get the select box to shrink in the flexbox otherwise...
         position: absolute !important;
         width: -webkit-fill-available !important;
     }
 }

 @keyframes -global-light-up {
     from {
         background-color: var(--color-yellow-400);
     }
     to {
         background-color: none;
     }
 }

 .updated {
     animation: light-up 1s ease-out;
     :global(.svelte-select) {
         animation: light-up 1s ease-out;
     }
 }

 :global(.svelte-select) {
     width: auto;
     --font-size: 13px;
     --height: 32px;
     --background: var(--input-background-fill);
     --selected-item-color: var(--body-text-color);
     --input-color: var(--body-text-color);
     --chevron-color: var(--body-text-color);
     --border: 1px solid var(--input-border-color);
     --border-hover: 1px solid var(--input-border-color-hover);
     --border-focused: 1px solid var(--neutral-400);
     --border-radius-focused: 0px;
     --border-radius: 0px;
     --list-background: var(--comfy-dropdown-list-background);
     --item-border: var(--comfy-dropdown-border-color);
     --item-color: var(--body-text-color);
     --item-color-hover: var(--comfy-dropdown-item-color-hover);
     --item-background-hover: var(--comfy-dropdown-item-background-hover);
     --item-color-active: var(--comfy-dropdown-item-color-active);
     --item-background-active: var(--comfy-dropdown-item-background-active);
     --disabled-color: var(--comfy-disabled-textbox-text-color);
     --disabled-border-color: var(--comfy-disabled-textbox-border-color);
     --disabled-background: var(--comfy-disabled-textbox-background-fill);
 }


 :global(.svelte-select.disabled) {
     --input-color: var(--comfy-disabled-textbox-text-color) !important;
     --selected-item-color: var(--comfy-disabled-textbox-text-color) !important;
 }

 :global(.svelte-select-list) {
     z-index: var(--layer-top) !important;
     overflow-y: initial !important;
     width: auto !important; // seems floating-ui overrides listAutoWidth
 }

 .container {
     border-top: 1px solid #333;
     border-bottom: 1px solid #333;

     height: 100%
 }

 .comfy-select-list {
     --maxLabelWidth: 100;
     font-size: 14px;
     width: min(calc((var(--maxLabelWidth) + 10) * 1ch), 50vw);
     color: var(--item-color);

     > :global(.virtual-list-wrapper) {
         box-shadow: var(--block-shadow);
         background-color: var(--list-background);
     }

     .comfy-empty-list {
         height: 100%;
         display: flex;
         justify-content: center;
         align-items: center;
         font-size: xx-large;
         color: var(--neutral-400)
     }

     .comfy-select-item {
         border: 1px solid var(--item-border);
         border-top: none;
         white-space: nowrap;
         overflow: hidden;
         text-overflow: ellipsis;
         display: flex;
         align-items: center;
         background-color: var(--list-background);

         font-size: 14px;
         padding: 0.2rem;

         .comfy-select-label {
         }

         &.mobile {
             font-size: 16px;
             padding: 1.2rem;
         }

         &.hover {
             color: var(--item-color-hover);
             background: var(--item-background-hover);
             cursor: pointer;
         }
         &.active {
             color: var(--item-color-active);
             background: var(--item-background-active);
         }
     }

     .details {
         background: white;
         border: 1px solid grey;
     }

     :global(svelte-virtual-list-row) {
         white-space: nowrap;
     }
 }
</style>
