<script lang="ts">
    import type FileViewState from "../models/FileViewState.svelte";
    import type XRefEntry from "../models/XRefEntry";

    const cellH = 25;
    const headerOffset = 2 * cellH;
    let { fState, height }: { fState: FileViewState; height: number } =
        $props();

    let fillerHeight: number = $state(0);

    let firstEntry = $state(0);
    let lastEntry = $state(100);
    let entriesToDisplay: XRefEntry[] = $derived(
        fState.xref_entries.slice(firstEntry, lastEntry),
    );

    let bodyViewHeight: number = $derived(Math.max(height - headerOffset, 0));
    let selectedPath: number | string | undefined = $derived(
        fState.getLastJump(),
    );
    let totalBodyHeight: number = $derived(
        Math.max(0, fState.xref_entries.length * cellH - headerOffset),
    );
    let scrollContainer: HTMLElement;

    $effect(() => {
        if (typeof selectedPath === "number") {
            smoothScrollTo(scrollContainer, selectedPath);
        }
    });

    function smoothScrollTo(scrollContainer: HTMLElement, target: number) {
        const targetY = Math.max(target, 0) * cellH;
        const startY = scrollContainer.scrollTop;

        if (
            targetY - startY > 0 &&
            targetY - startY < Math.max(height - headerOffset, 0)
        ) {
            return;
        }

        const duration = 500;
        const diff = targetY - startY;
        const startTime = Date.now();

        function animate() {
            const elapsed = Date.now() - startTime;
            const progress = Math.min(elapsed / duration, 1); // Normalize to [0,1]

            scrollContainer.scrollTop = startY + diff * easeInOutQuad(progress);

            if (progress < 1) {
                requestAnimationFrame(animate);
            }
        }

        function easeInOutQuad(t: number) {
            return t < 0.5 ? 2 * t * t : 1 - Math.pow(-2 * t + 2, 2) / 2;
        }

        requestAnimationFrame(animate);
    }

    function handleScroll(event: Event & { currentTarget: HTMLElement }) {
        let scrollY = event.currentTarget.scrollTop;
        firstEntry = Math.floor(scrollY / cellH);
        lastEntry = Math.ceil((scrollY + bodyViewHeight) / cellH);

        fillerHeight = firstEntry * cellH;
    }
</script>

<div class="overflow-x-auto" style="height: {height}px;">
    <div class="w-[281px]">
        <table>
            <thead>
                <tr>
                    <td class="cell t-header border-forge-prim">Obj Nr</td>
                    <td class="cell t-header border-forge-prim">Gen Nr</td>
                    <td class="cell t-header border-forge-prim">Type</td>
                    <td class="cell t-header border-forge-sec">Offset</td>
                </tr>
                <tr
                    class={selectedPath === "Trailer"
                        ? "bg-forge-acc"
                        : "hover:bg-forge-sec"}
                    onclick={() => fState.selectXref(undefined)}
                >
                    <td class="cell t-data">Trailer</td>
                    <td class="cell t-data">65535</td>
                    <td class="cell t-data">Dictionary</td>
                    <td class="cell t-data">End of file</td>
                </tr>
            </thead>
        </table>
        <div
            class="scrollContainer"
            style="height: {bodyViewHeight}px"
            onscroll={handleScroll}
            bind:this={scrollContainer}
        >
            <div class="container" style="height: {totalBodyHeight}px">
                <table>
                    <tbody>
                        <tr class="filler" style="height: {fillerHeight}px"
                        ></tr>
                        {#each entriesToDisplay as entry}
                            <tr
                                class={selectedPath === entry.obj_num
                                    ? "bg-forge-acc"
                                    : "hover:bg-forge-sec"}
                                onclick={() => fState.selectXref(entry)}
                            >
                                <td class="cell t-data">{entry.obj_num}</td>
                                <td class="cell t-data">{entry.gen_num}</td>
                                <td class="cell t-data">{entry.obj_type}</td>
                                <td class="cell t-data">{entry.offset}</td>
                            </tr>
                        {/each}
                    </tbody>
                </table>
            </div>
        </div>
    </div>
</div>

<style lang="postcss">
    .t-header {
        @apply uppercase text-xs text-forge-text p-5 bg-forge-sec border-r;
        cursor: default;
    }

    .t-data {
        @apply border text-xs text-forge-text border-forge-sec;
    }

    .cell {
        @apply min-w-[70px] w-[70px] p-1 m-0;
        text-align: center;
    }

    .container {
        @apply border-forge-bound w-[281px];
    }

    .scrollContainer {
        overflow-y: auto;
    }
</style>
