<!DOCTYPE html>
<html lang="en" class="h-full">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Marlin Grounding Event Visualizer</title>
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;500;600;700&display=swap" rel="stylesheet">
    <script src="https://cdn.tailwindcss.com"></script>
    <script>
        tailwind.config = {
            theme: {
                extend: {
                    fontFamily: {
                        sans: ['Outfit', 'sans-serif'],
                    },
                    colors: {
                        parchment: {
                            DEFAULT: '#f4ecd8',
                            dark: '#e8dcc4',
                        },
                        ink: {
                            DEFAULT: '#2b2220',
                            light: '#5c4a46',
                        },
                        brand: {
                            red: '#bf3131',
                            'red-light': '#d45a5a',
                            'red-dark': '#8c2222',
                        }
                    }
                }
            }
        }
    </script>
    <style>
        :root {
            --parchment: #f4ecd8;
            --parchment-dark: #e8dcc4;
            --ink: #2b2220;
            --ink-light: #5c4a46;
            --accent-red: #bf3131;
            --accent-red-light: #d45a5a;
            --accent-red-dark: #8c2222;
        }

        ::-webkit-scrollbar {
            width: 6px;
        }

        ::-webkit-scrollbar-track {
            background: transparent;
        }

        ::-webkit-scrollbar-thumb {
            background: var(--parchment-dark);
            border-radius: 3px;
        }

        ::-webkit-scrollbar-thumb:hover {
            background: var(--ink-light);
        }
    </style>
</head>

<body class="bg-parchment text-ink font-sans h-full flex flex-col antialiased">
    <!-- Main Content Container -->
    <main class="flex-1 grid grid-cols-1 lg:grid-cols-12 gap-6 p-6 max-w-7xl mx-auto w-full overflow-hidden min-h-0">
        <!-- Player Column -->
        <section class="lg:col-span-8 flex flex-col gap-4 min-h-0">
            <div
                class="bg-parchment-dark/10 border border-parchment-dark/40 rounded-2xl p-4 shadow-sm flex flex-col gap-4 flex-1 min-h-0">
                <!-- Video Container -->
                <div class="relative bg-black rounded-xl overflow-hidden flex-1 min-h-0 shadow-inner">
                    <video id="video-player" controls preload="auto" class="w-full h-full object-contain">
                        <source id="video-source" src="" type="video/mp4">
                        Your browser does not support the video tag.
                    </video>
                </div>

                <!-- Custom Interactive Timeline -->
                <div class="relative w-full h-7 bg-parchment-dark/30 rounded-lg cursor-pointer overflow-hidden border border-parchment-dark/50 flex-shrink-0"
                    id="custom-timeline" title="Click to seek">
                    <div class="absolute left-0 top-0 bottom-0 bg-brand-red/10 pointer-events-none transition-[width] duration-75"
                        id="timeline-progress"></div>
                    <div class="absolute top-0 bottom-0 w-[3px] bg-brand-red shadow-[0_0_8px_rgba(191,49,49,0.5)] pointer-events-none left-0 transition-[left] duration-75"
                        id="timeline-playhead"></div>
                </div>

                <!-- Controls & Seek Info -->
                <div class="flex justify-between items-center flex-wrap gap-3 pt-1 flex-shrink-0">
                    <div class="text-sm font-medium font-mono text-ink-light">
                        <span id="current-time-display" class="text-ink font-semibold">00:00.00</span>
                        <span class="mx-1">/</span>
                        <span id="duration-display">00:00.00</span>
                    </div>
                    <div class="flex items-center flex-wrap gap-3">
                        <!-- Local file fallback: Chrome blocks file://→file:// <source> loads -->
                        <input type="file" id="local-file-input" accept="video/*" class="hidden">
                        <label for="local-file-input" id="local-file-label"
                            class="text-xs font-semibold px-2.5 py-1 rounded-full bg-parchment-dark text-ink-light border border-parchment-dark hover:bg-brand-red hover:text-parchment hover:border-brand-red cursor-pointer transition-colors duration-200 select-none">
                            Load video file…
                        </label>
                        <span id="file-hint"
                            class="hidden text-xs font-semibold text-brand-red">
                            Couldn't auto-load the video — pick it manually
                        </span>
                        <div id="stats"
                            class="text-xs font-semibold px-2.5 py-1 rounded-full bg-parchment-dark text-ink-light">
                            Loading...
                        </div>
                    </div>
                </div>
            </div>
        </section>

        <!-- Events List Column -->
        <section class="lg:col-span-4 flex flex-col gap-3 overflow-hidden min-h-0">
            <h2 class="text-sm font-bold text-ink-light/80 uppercase tracking-wider px-1 flex-shrink-0">Detected Event
                Clips</h2>
            <div class="flex-1 overflow-y-auto pr-1 flex flex-col gap-3" id="events-list">
                <!-- Event Cards are dynamically injected -->
            </div>
        </section>
    </main>

    <script>
        // Injected data placeholders
        const DATA = __DATA_JSON_PLACEHOLDER__;
        const VIDEO_PATH = "__VIDEO_PATH_PLACEHOLDER__";

        const videoPlayer = document.getElementById('video-player');
        const videoSource = document.getElementById('video-source');
        const duration = DATA.duration_seconds;

        // Set video source
        videoSource.src = VIDEO_PATH;
        videoPlayer.load();

        function formatTime(sec) {
            const m = Math.floor(sec / 60);
            const s = Math.floor(sec % 60);
            const ms = Math.floor((sec % 1) * 100);
            return `${m.toString().padStart(2, '0')}:${s.toString().padStart(2, '0')}.${ms.toString().padStart(2, '0')}`;
        }

        function escapeHtml(s){return String(s).replace(/[&<>"']/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[c]));}

        document.getElementById('stats').innerText = `${DATA.events.length} Matches Found • ${Math.round(duration)}s`;

        const timeline = document.getElementById('custom-timeline');
        const listContainer = document.getElementById('events-list');

        let activeTargetEnd = null;
        let isProgrammaticSeek = false;
        let isProgrammaticPlay = false;

        DATA.events.forEach((event, idx) => {
            // Render timeline highlight
            const startPct = (event.global_start / duration) * 100;
            const endPct = (event.global_end / duration) * 100;
            const widthPct = endPct - startPct;

            const segment = document.createElement('div');
            segment.className = 'absolute top-1 bottom-1 bg-brand-red/30 hover:bg-brand-red/60 border-l border-r border-brand-red/50 rounded-sm transition-all duration-200 cursor-pointer';
            segment.style.left = `${startPct}%`;
            segment.style.width = `${widthPct}%`;
            segment.title = `Match ${idx + 1}: ${formatTime(event.global_start)} - ${formatTime(event.global_end)}`;
            segment.addEventListener('click', (e) => {
                e.stopPropagation();
                seekTo(event.global_start, event.global_end);
            });
            timeline.appendChild(segment);

            // Render list card
            const card = document.createElement('div');
            card.id = `card-${idx}`;
            card.className = 'event-card bg-parchment-dark/10 border border-parchment-dark/40 rounded-xl p-4 cursor-pointer transition-all duration-200 hover:border-brand-red/40 hover:shadow-sm flex flex-col gap-2 border-l-4 border-l-transparent';

            card.innerHTML = `
                <div class="flex justify-between items-center">
                    <span class="text-sm font-semibold text-ink">Match ${idx + 1}</span>
                    <span class="text-xs font-semibold text-brand-red bg-brand-red/10 px-2 py-0.5 rounded-md border border-brand-red/20">${formatTime(event.global_start)} - ${formatTime(event.global_end)}</span>
                </div>
                <p class="text-xs text-ink-light line-clamp-2">Query match: "${escapeHtml(event.description)}"</p>
                <div class="flex justify-between items-center text-[10px] text-ink-light/70 font-medium mt-1">
                    <span>Source Chunk: ${event.chunk_id}</span>
                    <span>Duration: ${(event.global_end - event.global_start).toFixed(1)}s</span>
                </div>
            `;

            card.addEventListener('click', () => {
                seekTo(event.global_start, event.global_end);
            });
            listContainer.appendChild(card);
        });

        function seekTo(seconds, endSeconds = null) {
            activeTargetEnd = endSeconds;
            isProgrammaticSeek = true;
            isProgrammaticPlay = true;
            videoPlayer.currentTime = seconds;
            videoPlayer.play();
        }

        timeline.addEventListener('click', (e) => {
            const rect = timeline.getBoundingClientRect();
            const clickX = e.clientX - rect.left;
            const pct = clickX / rect.width;
            seekTo(pct * duration, null);
        });

        videoPlayer.addEventListener('seeking', () => {
            if (!isProgrammaticSeek) {
                activeTargetEnd = null;
            }
            isProgrammaticSeek = false;
        });

        videoPlayer.addEventListener('play', () => {
            if (!isProgrammaticPlay) {
                activeTargetEnd = null;
            }
            isProgrammaticPlay = false;
        });

        const progressEl = document.getElementById('timeline-progress');
        const playheadEl = document.getElementById('timeline-playhead');
        const curTimeEl = document.getElementById('current-time-display');
        const durTimeEl = document.getElementById('duration-display');

        videoPlayer.addEventListener('timeupdate', () => {
            const curTime = videoPlayer.currentTime;

            // Check if programmatic playback target has ended
            if (activeTargetEnd !== null && curTime >= activeTargetEnd) {
                videoPlayer.pause();
                activeTargetEnd = null;
            }

            const pct = (curTime / duration) * 100;
            progressEl.style.width = `${pct}%`;
            playheadEl.style.left = `${pct}%`;
            curTimeEl.innerText = formatTime(curTime);

            DATA.events.forEach((event, idx) => {
                const el = document.getElementById(`card-${idx}`);
                if (el) {
                    if (curTime >= event.global_start && curTime <= event.global_end) {
                        if (!el.classList.contains('active-card')) {
                            el.classList.add('active-card', 'bg-brand-red/5', 'border-l-brand-red', 'border-brand-red/40');
                            el.classList.remove('bg-parchment-dark/10');
                            el.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
                        }
                    } else {
                        el.classList.remove('active-card', 'bg-brand-red/5', 'border-l-brand-red', 'border-brand-red/40');
                        el.classList.add('bg-parchment-dark/10');
                    }
                }
            });
        });

        videoPlayer.addEventListener('loadedmetadata', () => {
            durTimeEl.innerText = formatTime(videoPlayer.duration || duration);
        });

        const fileInput = document.getElementById('local-file-input');
        const fileLabel = document.getElementById('local-file-label');
        const fileHint = document.getElementById('file-hint');

        // Reveal the picker when the file:// source can't auto-load (Chrome blocks
        // file://→file:// media). Highlight the trigger and surface the hint.
        function surfacePicker() {
            if (fileHint) {
                fileHint.classList.remove('hidden');
            }
            if (fileLabel) {
                fileLabel.classList.add('bg-brand-red', 'text-parchment', 'border-brand-red');
            }
        }

        if (fileInput) {
            fileInput.addEventListener('change', (e) => {
                const file = e.target.files[0];
                if (file) {
                    const objectURL = URL.createObjectURL(file);
                    videoSource.src = objectURL;
                    videoPlayer.load();
                    videoPlayer.play();
                    if (fileHint) {
                        fileHint.classList.add('hidden');
                    }
                    if (fileLabel) {
                        fileLabel.classList.remove('bg-brand-red', 'text-parchment', 'border-brand-red');
                    }
                }
            });
        }

        videoSource.addEventListener('error', surfacePicker);
        videoPlayer.addEventListener('error', surfacePicker);
    </script>
</body>

</html>