<!--
    Component: FontList
    Renders font list for A/B comparison with animated selection
-->
<script lang="ts">
import {
    DEFAULT_FONT_WEIGHT,
    FontApplicator,
    FontVirtualList,
    type UnifiedFont,
} from '$entities/Font';
import {
    Button,
    Label,
} from '$shared/ui';
import DotIcon from '@lucide/svelte/icons/dot';
import { cubicOut } from 'svelte/easing';
import { crossfade } from 'svelte/transition';
import { comparisonStore } from '../../model';

const side = $derived(comparisonStore.side);
let prevIndexA: number | null = null;
let prevIndexB: number | null = null;
let selectedIndexA: number | null = null;
let selectedIndexB: number | null = null;
let pendingDirection: 1 | -1 = 1;

const [send, receive] = crossfade({
    duration: 300,
    easing: cubicOut,
    fallback(node) {
        // Read pendingDirection synchronously — no reactive timing issues
        const fromY = pendingDirection * (node.closest('[data-font-list]')?.clientHeight ?? 300);
        return {
            duration: 300,
            easing: cubicOut,
            css: t => `transform: translateY(${fromY * (1 - t)}px);`,
        };
    },
});

function handleSelect(font: UnifiedFont, index: number) {
    if (side === 'A') {
        if (prevIndexA !== null) {
            pendingDirection = index > prevIndexA ? -1 : 1;
        }
        prevIndexA = index;
        selectedIndexA = index;
        comparisonStore.fontA = font;
    } else if (side === 'B') {
        if (prevIndexB !== null) {
            pendingDirection = index > prevIndexB ? -1 : 1;
        }
        prevIndexB = index;
        selectedIndexB = index;
        comparisonStore.fontB = font;
    }
}

// When side switches, compute direction from relative positions of A vs B
$effect(() => {
    const _ = side; // track side
    if (selectedIndexA !== null && selectedIndexB !== null) {
        // Switching TO B means dot moves toward B's position relative to A
        pendingDirection = side === 'B'
            ? (selectedIndexB > selectedIndexA ? 1 : -1)
            : (selectedIndexA > selectedIndexB ? 1 : -1);
    }
});
</script>

<div class="flex-1 min-h-0 h-full">
    <div class="py-2 relative flex flex-col min-h-0 h-full">
        <div class="py-2 mx-6 sticky border-b border-subtle">
            <Label font="primary" variant="muted" bold size="sm" uppercase>
                Typeface Selection
            </Label>
        </div>
        <FontVirtualList
            data-font-list
            weight={DEFAULT_FONT_WEIGHT}
            itemHeight={45}
            class="bg-transparent min-h-0 h-full scroll-stable py-2 pl-6 pr-4"
        >
            {#snippet children({ item: font, index })}
                {@const isSelectedA = font.id === comparisonStore.fontA?.id}
                {@const isSelectedB = font.id === comparisonStore.fontB?.id}
                {@const active = (side === 'A' && isSelectedA) || (side === 'B' && isSelectedB)}

                <Button
                    variant="tertiary"
                    {active}
                    onclick={() => handleSelect(font, index)}
                    class="w-full px-3 md:px-4 py-2.5 md:py-3 flex !justify-between text-left text-sm"
                    iconPosition="right"
                >
                    <FontApplicator {font}>{font.name}</FontApplicator>

                    {#snippet icon()}
                        {#if active}
                            <div
                                in:receive={{ key: 'active-dot' }}
                                out:send={{ key: 'active-dot' }}
                            >
                                <DotIcon class="size-8 stroke-brand" />
                            </div>
                        {:else if isSelectedA || isSelectedB}
                            <div
                                in:receive={{ key: 'inactive-dot' }}
                                out:send={{ key: 'inactive-dot' }}
                            >
                                <DotIcon class="size-8 stroke-neutral-300 dark:stroke-neutral-600" />
                            </div>
                        {/if}
                    {/snippet}
                </Button>
            {/snippet}
        </FontVirtualList>
    </div>
</div>
