<script>
    import { onMount, onDestroy } from 'svelte';
    import BackButton from './BackButton.svelte';
    import OpfsDisabledBanner from './OpfsDisabledBanner.svelte';
    import Carousel from './Carousel.svelte';
    import MissionScoresEditor from './save-editor/MissionScoresEditor.svelte';
    import SkyColorEditor from './save-editor/SkyColorEditor.svelte';
    import LightPositionEditor from './save-editor/LightPositionEditor.svelte';
    import VehicleEditor from './save-editor/VehicleEditor.svelte';
    import ActorEditor from './save-editor/ActorEditor.svelte';
    import PlantEditor from './save-editor/PlantEditor.svelte';
    import BuildingEditor from './save-editor/BuildingEditor.svelte';
    import { fetchBitmapAsURL } from '../core/assetLoader.js';
    import { saveEditorState, currentPage, opfsDisabled, savesVersion } from '../stores.js';
    import { getOpfsRoot } from '../core/opfs.js';
    import { listSaveSlots, updateSaveSlot, updatePlayerName } from '../core/savegame/index.js';
    import { Actor, ActorNames } from '../core/savegame/constants.js';

    let loading = true;
    let error = null;
    let slots = [];
    let selectedSlot = null;

    // Tab state
    let activeTab = 'player';
    let openSection = 'name';

    const saveTabs = [
        { id: 'player', label: 'Player', firstSection: 'name' },
        { id: 'scores', label: 'Scores', firstSection: null },
        { id: 'island', label: 'Island', firstSection: 'skycolor' },
        { id: 'vehicles', label: 'Vehicles', firstSection: null },
        { id: 'actors', label: 'Actors', firstSection: null },
        { id: 'plants', label: 'Plants', firstSection: null },
        { id: 'buildings', label: 'Buildings', firstSection: null }
    ];

    // Reset state when navigating to this page
    $: if ($currentPage === 'save-editor') {
        selectedSlot = null;
        activeTab = 'player';
        openSection = 'name';
    }

    // Reload saves from OPFS when navigating to this page or after cloud sync
    $: if ($currentPage === 'save-editor' && !$opfsDisabled) {
        $savesVersion;
        loadSlots();
    }

    // Name editing state (7 characters)
    let nameSlots = ['', '', '', '', '', '', ''];
    let slotRefs = [];

    // Character/Act state
    let currentAct = 0;
    let actorId = 1;

    // Character icons — loaded from SI file bitmaps
    const iconNames = ['pepper', 'mama', 'papa', 'nick', 'laura'];
    let characterIcons = {};
    let iconUrls = [];

    // Carousel state (bound from Carousel component)
    let carouselHasDragged = false;
    let slotCarousel;
    let tabCarousel;

    // Slot carousel navigation
    $: selectedSlotIndex = existingSlots.findIndex(s => s.slotNumber === selectedSlot);
    $: hasSlotPrev = selectedSlotIndex > 0;
    $: hasSlotNext = selectedSlotIndex >= 0 && selectedSlotIndex < existingSlots.length - 1;

    function selectPrevSlot() {
        if (!hasSlotPrev) return;
        const newIdx = selectedSlotIndex - 1;
        handleSlotSelect(existingSlots[newIdx].slotNumber);
        slotCarousel?.scrollToIndex(newIdx);
    }

    function selectNextSlot() {
        if (!hasSlotNext) return;
        const newIdx = selectedSlotIndex + 1;
        handleSlotSelect(existingSlots[newIdx].slotNumber);
        slotCarousel?.scrollToIndex(newIdx);
    }

    // Tab carousel navigation
    $: activeTabIndex = saveTabs.findIndex(t => t.id === activeTab);
    $: hasTabPrev = activeTabIndex > 0;
    $: hasTabNext = activeTabIndex < saveTabs.length - 1;

    function selectPrevTab() {
        if (!hasTabPrev) return;
        const newIdx = activeTabIndex - 1;
        switchTab(saveTabs[newIdx]);
        tabCarousel?.scrollToIndex(newIdx);
    }

    function selectNextTab() {
        if (!hasTabNext) return;
        const newIdx = activeTabIndex + 1;
        switchTab(saveTabs[newIdx]);
        tabCarousel?.scrollToIndex(newIdx);
    }

    onMount(async () => {
        const root = await getOpfsRoot();
        if (!root) {
            opfsDisabled.set(true);
            loading = false;
            return;
        }

        await loadSlots();

        // Load character icons from SI file in background
        const urls = await Promise.all(iconNames.flatMap(name => [
            fetchBitmapAsURL(name),
            fetchBitmapAsURL(`${name}-selected`)
        ]));
        iconUrls = urls;
        characterIcons = {
            [Actor.PEPPER]: { normal: urls[0], selected: urls[1] },
            [Actor.MAMA]: { normal: urls[2], selected: urls[3] },
            [Actor.PAPA]: { normal: urls[4], selected: urls[5] },
            [Actor.NICK]: { normal: urls[6], selected: urls[7] },
            [Actor.LAURA]: { normal: urls[8], selected: urls[9] }
        };
    });

    onDestroy(() => {
        for (const url of iconUrls) {
            if (url) URL.revokeObjectURL(url);
        }
    });

    async function loadSlots() {
        loading = true;
        error = null;

        try {
            slots = await listSaveSlots();
            saveEditorState.update(s => ({ ...s, slots, loading: false, error: null }));
        } catch (e) {
            error = e.message;
            saveEditorState.update(s => ({ ...s, loading: false, error: e.message }));
        } finally {
            loading = false;
        }
    }

    function handleSlotSelect(slotNumber) {
        if (carouselHasDragged) return;
        selectedSlot = slotNumber;
        saveEditorState.update(s => ({ ...s, selectedSlot: slotNumber }));
    }

    async function handleHeaderUpdate(updates) {
        if (selectedSlot === null) return;

        try {
            const updated = await updateSaveSlot(selectedSlot, { header: updates });
            if (updated) {
                slots = slots.map(s =>
                    s.slotNumber === selectedSlot
                        ? { ...s, header: updated.header }
                        : s
                );
            }
        } catch (e) {
            console.error('Failed to update save:', e);
        }
    }

    async function handleMissionUpdate(missionUpdate) {
        if (selectedSlot === null) return;

        try {
            const updated = await updateSaveSlot(selectedSlot, { missionScore: missionUpdate });
            if (updated) {
                slots = slots.map(s =>
                    s.slotNumber === selectedSlot
                        ? { ...s, missions: updated.missions }
                        : s
                );
            }
        } catch (e) {
            console.error('Failed to update mission score:', e);
        }
    }

    async function handleVariableUpdate(update) {
        if (selectedSlot === null) return;

        try {
            const updated = await updateSaveSlot(selectedSlot, update);
            if (updated) {
                slots = slots.map(s =>
                    s.slotNumber === selectedSlot
                        ? { ...s, variables: updated.variables, act1State: updated.act1State, characters: updated.characters, plants: updated.plants, buildings: updated.buildings, buildingsOffset: updated.buildingsOffset, nextVariant: updated.nextVariant, nextVariantOffset: updated.nextVariantOffset }
                        : s
                );
            }
        } catch (e) {
            console.error('Failed to update variable:', e);
        }
    }

    // Tab/section functions
    function switchTab(tab) {
        activeTab = tab.id;
        openSection = tab.firstSection;
    }

    function toggleSection(sectionId) {
        openSection = openSection === sectionId ? null : sectionId;
    }

    // Name editing functions
    async function saveNameFromSlots() {
        const newName = nameSlots.join('').replace(/[^A-Z]/g, '');
        if (newName.length === 0) return;

        const success = await updatePlayerName(currentSlot.slotNumber, newName);
        if (success) {
            slots = slots.map(s =>
                s.slotNumber === selectedSlot
                    ? { ...s, playerName: newName }
                    : s
            );
        }
    }

    function handleSlotBeforeInput(index, e) {
        if (!e.data) return;

        const char = e.data.toUpperCase();
        if (!/^[A-Z]$/.test(char)) {
            e.preventDefault();
            return;
        }

        e.preventDefault();
        nameSlots[index] = char;
        nameSlots = [...nameSlots];
        saveNameFromSlots();

        if (index < 6) {
            slotRefs[index + 1]?.focus();
        }
    }

    function getFilledCount() {
        return nameSlots.filter(c => c !== '').length;
    }

    function handleSlotKeydown(index, e) {
        if (e.key === 'Backspace') {
            if (nameSlots[index] === '' && index > 0) {
                if (getFilledCount() > 1 || nameSlots[index - 1] === '') {
                    slotRefs[index - 1]?.focus();
                    if (nameSlots[index - 1] !== '' && getFilledCount() > 1) {
                        nameSlots[index - 1] = '';
                        nameSlots = [...nameSlots];
                        saveNameFromSlots();
                    }
                }
                e.preventDefault();
            } else if (nameSlots[index] !== '') {
                if (getFilledCount() > 1) {
                    nameSlots[index] = '';
                    nameSlots = [...nameSlots];
                    saveNameFromSlots();
                }
                e.preventDefault();
            }
        } else if (e.key === 'ArrowLeft' && index > 0) {
            slotRefs[index - 1]?.focus();
            e.preventDefault();
        } else if (e.key === 'ArrowRight' && index < 6) {
            slotRefs[index + 1]?.focus();
            e.preventDefault();
        } else if (e.key === 'Delete') {
            if (getFilledCount() > 1 && nameSlots[index] !== '') {
                nameSlots[index] = '';
                nameSlots = [...nameSlots];
                saveNameFromSlots();
            }
            e.preventDefault();
        }
    }

    function handleSlotFocus(e) {
        e.target.select();
        e.target.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'nearest' });
    }

    // Character handler
    function handleActorSelect(id) {
        actorId = id;
        handleHeaderUpdate({ actorId: id });
    }

    // Actor options (ordered: Mama, Papa, Pepper, Nick, Laura)
    const actorOptions = [
        { id: Actor.MAMA, name: ActorNames[Actor.MAMA] },
        { id: Actor.PAPA, name: ActorNames[Actor.PAPA] },
        { id: Actor.PEPPER, name: ActorNames[Actor.PEPPER] },
        { id: Actor.NICK, name: ActorNames[Actor.NICK] },
        { id: Actor.LAURA, name: ActorNames[Actor.LAURA] }
    ];

    $: existingSlots = slots.filter(s => s.exists && s.playerName);
    $: currentSlot = slots.find(s => s.slotNumber === selectedSlot);

    // Update local state when currentSlot changes
    $: if (currentSlot?.header) {
        currentAct = currentSlot.header.currentAct;
        actorId = currentSlot.header.actorId;
    }

    // Update name slots when player name changes
    $: if (currentSlot?.playerName) {
        const name = currentSlot.playerName.toUpperCase();
        nameSlots = Array.from({ length: 7 }, (_, i) => name[i] || '');
    }
</script>

<div id="save-editor" class="page-content">
    <BackButton />
    <OpfsDisabledBanner />
    <div class="page-inner-content config-layout">
        <div class="config-art-panel">
            <img src="images/save.webp" alt="LEGO Island Save Editor">
        </div>
        <div class="config-main">
            {#if loading || error || existingSlots.length > 0}
                <Carousel bind:this={slotCarousel} bind:hasDragged={carouselHasDragged} onPrev={selectPrevSlot} onNext={selectNextSlot} hasPrev={hasSlotPrev} hasNext={hasSlotNext}>
                    {#if loading}
                        <span class="save-status-text">Loading save files...</span>
                    {:else if error}
                        <span class="save-status-text error">{error}</span>
                    {:else}
                        {#each existingSlots as slot}
                            <button
                                type="button"
                                class="save-slot-card"
                                class:selected={selectedSlot === slot.slotNumber}
                                onclick={() => handleSlotSelect(slot.slotNumber)}
                            >
                                {#if characterIcons[slot.header?.actorId]?.selected}
                                    <img
                                        src={characterIcons[slot.header?.actorId].selected}
                                        alt={ActorNames[slot.header?.actorId] || 'Character'}
                                        class="slot-character-icon"
                                        draggable="false"
                                    />
                                {/if}
                                <span class="slot-name">{slot.playerName}</span>
                            </button>
                        {/each}
                    {/if}
                </Carousel>
            {/if}

            {#if !loading && !error && existingSlots.length === 0}
                <div class="no-saves-state">
                    <img src="images/callfail.webp" alt="" class="no-saves-image" />
                    <span class="no-saves-title">No save files found</span>
                    <p class="no-saves-description">
                        Start playing LEGO Island and your save will appear here automatically.
                    </p>
                </div>
            {:else if !loading && !error && existingSlots.length > 0 && !currentSlot}
                <div class="no-saves-state">
                    <img src="images/register.webp" alt="" class="no-saves-image" />
                    <span class="no-saves-title">Select a save file above</span>
                    <p class="no-saves-description">
                        Choose a save slot to view and edit your player name, character, and high scores.
                    </p>
                </div>
            {/if}

            {#if currentSlot && currentSlot.exists}
                <div class="config-tabs">
                    <div class="config-tab-buttons tab-carousel-wrapper">
                        <Carousel bind:this={tabCarousel} gap={5} onPrev={selectPrevTab} onNext={selectNextTab} hasPrev={hasTabPrev} hasNext={hasTabNext}>
                            {#each saveTabs as tab}
                                <button
                                    class="config-tab-btn"
                                    class:active={activeTab === tab.id}
                                    onclick={() => switchTab(tab)}
                                >
                                    {tab.label}
                                </button>
                            {/each}
                        </Carousel>
                    </div>

                    <!-- Player Tab -->
                    <div class:hidden={activeTab !== 'player'}>
                        <div class="config-section-card">
                            <button type="button" class="config-card-header" onclick={() => toggleSection('name')}>
                                Name
                            </button>
                            <div class="config-card-content" class:open={openSection === 'name'}>
                                <div class="section-inner">
                                    <div class="name-slots">
                                        {#each nameSlots as char, i}
                                            <input
                                                type="text"
                                                class="name-slot"
                                                value={char}
                                                maxlength="1"
                                                onbeforeinput={(e) => handleSlotBeforeInput(i, e)}
                                                onkeydown={(e) => handleSlotKeydown(i, e)}
                                                onfocus={handleSlotFocus}
                                                bind:this={slotRefs[i]}
                                            />
                                        {/each}
                                    </div>
                                </div>
                            </div>
                        </div>

                        <div class="config-section-card">
                            <button type="button" class="config-card-header" onclick={() => toggleSection('character')}>
                                Character
                            </button>
                            <div class="config-card-content" class:open={openSection === 'character'}>
                                <div class="section-inner">
                                    <div class="character-icons">
                                        {#each actorOptions as actor}
                                            <button
                                                type="button"
                                                class="character-icon-btn"
                                                class:selected={actorId === actor.id}
                                                onclick={() => handleActorSelect(actor.id)}
                                                title={actor.name}
                                            >
                                                {#if characterIcons[actor.id]}
                                                    <img
                                                        src={actorId === actor.id
                                                            ? characterIcons[actor.id].selected
                                                            : characterIcons[actor.id].normal}
                                                        alt={actor.name}
                                                    />
                                                {/if}
                                            </button>
                                        {/each}
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>

                    <!-- Scores Tab -->
                    <div class:hidden={activeTab !== 'scores'}>
                        <MissionScoresEditor
                            slot={currentSlot}
                            onUpdate={handleMissionUpdate}
                        />
                    </div>

                    <!-- Island Tab -->
                    <div class:hidden={activeTab !== 'island'}>
                        <div class="config-section-card">
                            <button type="button" class="config-card-header" onclick={() => toggleSection('skycolor')}>
                                Sky Color
                            </button>
                            <div class="config-card-content" class:open={openSection === 'skycolor'}>
                                <SkyColorEditor slot={currentSlot} onUpdate={handleVariableUpdate} />
                            </div>
                        </div>

                        <div class="config-section-card">
                            <button type="button" class="config-card-header" onclick={() => toggleSection('lightposition')}>
                                Light Position
                            </button>
                            <div class="config-card-content" class:open={openSection === 'lightposition'}>
                                <LightPositionEditor slot={currentSlot} onUpdate={handleVariableUpdate} />
                            </div>
                        </div>
                    </div>

                    <!-- Vehicles Tab -->
                    <div class:hidden={activeTab !== 'vehicles'}>
                        {#if $currentPage === 'save-editor'}
                            <VehicleEditor slot={currentSlot} onUpdate={handleVariableUpdate} />
                        {/if}
                    </div>

                    <!-- Actors Tab -->
                    <div class:hidden={activeTab !== 'actors'}>
                        {#if $currentPage === 'save-editor'}
                            <ActorEditor slot={currentSlot} onUpdate={handleVariableUpdate} />
                        {/if}
                    </div>

                    <!-- Plants Tab -->
                    <div class:hidden={activeTab !== 'plants'}>
                        {#if $currentPage === 'save-editor'}
                            <PlantEditor slot={currentSlot} onUpdate={handleVariableUpdate} />
                        {/if}
                    </div>

                    <!-- Buildings Tab -->
                    <div class:hidden={activeTab !== 'buildings'}>
                        {#if $currentPage === 'save-editor'}
                            <BuildingEditor slot={currentSlot} onUpdate={handleVariableUpdate} />
                        {/if}
                    </div>
                </div>
            {/if}
        </div>
    </div>
</div>

<style>
    :global(#save-editor > .page-inner-content > .config-main > .carousel) {
        margin-bottom: 15px;
    }

    .save-status-text {
        color: var(--color-text-muted);
        font-size: 0.9em;
        padding: 8px 0;
    }

    .save-status-text.error {
        color: #ff6b6b;
    }

    .no-saves-state {
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        text-align: center;
        padding: 48px 24px;
        flex: 1;
    }

    .no-saves-image {
        width: 100px;
        height: auto;
        margin-bottom: 16px;
        border-radius: 8px;
    }

    .no-saves-title {
        color: var(--color-text-light);
        font-size: 1.1em;
        font-weight: bold;
        margin-bottom: 8px;
    }

    .no-saves-description {
        color: var(--color-text-muted);
        font-size: 0.9em;
        line-height: 1.5;
        max-width: 280px;
        margin: 0;
    }

    .save-slot-card {
        display: flex;
        flex-direction: column;
        align-items: center;
        gap: 4px;
        padding: 6px 8px;
        min-width: 85px;
        background: var(--gradient-panel);
        border: 2px solid var(--color-border-medium);
        border-radius: 6px;
        cursor: pointer;
        transition: all 0.2s ease;
    }

    .save-slot-card:hover {
        border-color: var(--color-border-light);
        background: var(--gradient-hover);
    }

    .save-slot-card.selected {
        border-color: var(--color-primary);
        box-shadow: 0 0 8px var(--color-primary-glow);
    }

    .slot-character-icon {
        width: 32px;
        height: 37px;
    }

    .slot-name {
        color: var(--color-text-light);
        font-size: 0.75em;
        font-weight: bold;
    }

    .section-inner {
        padding-top: 4px;
        min-width: 0;
    }

    .name-slots {
        display: flex;
        gap: 4px;
        max-width: 100%;
        overflow-x: auto;
        scrollbar-width: none;
        -ms-overflow-style: none;
    }

    .name-slots::-webkit-scrollbar {
        display: none;
    }

    .name-slot {
        width: 36px;
        height: 36px;
        text-align: center;
        font-size: 1em;
        font-weight: bold;
        font-family: inherit;
        text-transform: uppercase;
        background: var(--color-bg-input);
        border: 1px solid var(--color-border-medium);
        border-radius: 4px;
        color: var(--color-text-light);
        padding: 0;
        flex-shrink: 0;
    }

    .name-slot:focus {
        outline: none;
        border-color: var(--color-primary);
        box-shadow: 0 0 0 2px rgba(255, 204, 0, 0.2);
    }

    .name-slot:hover {
        border-color: var(--color-border-light);
    }

    .character-icons {
        display: flex;
        gap: 4px;
    }

    .character-icon-btn {
        padding: 4px;
        background: var(--color-bg-input);
        border: 2px solid var(--color-border-medium);
        border-radius: 6px;
        cursor: pointer;
        transition: all 0.2s ease;
    }

    .character-icon-btn:hover {
        border-color: var(--color-border-light);
    }

    .character-icon-btn.selected {
        border-color: var(--color-primary);
    }

    .character-icon-btn img {
        width: 40px;
        height: 46px;
        display: block;
    }

    .tab-carousel-wrapper {
        display: block;
    }

    .tab-carousel-wrapper :global(.carousel) {
        gap: 4px;
    }

    .tab-carousel-wrapper :global(.carousel-track) {
        cursor: default;
    }

    .tab-carousel-wrapper :global(.carousel-track.dragging) {
        cursor: default;
    }

    @media (max-width: 768px) {
        .tab-carousel-wrapper {
            display: flex;
            flex-wrap: wrap;
            gap: 0;
        }

        .tab-carousel-wrapper :global(.carousel) {
            display: contents;
        }

        .tab-carousel-wrapper :global(.nav-btn) {
            display: none;
        }

        .tab-carousel-wrapper :global(.carousel-track) {
            display: contents;
        }
    }

    @media (max-width: 400px) {
        .name-slot {
            width: 32px;
            height: 32px;
            font-size: 0.9em;
        }

        .character-icon-btn img {
            width: 32px;
            height: 37px;
        }

        .slot-character-icon {
            width: 32px;
            height: 37px;
        }
    }
</style>
