var Module = {
    arguments: ['--ini', '/config/isle.ini'],
    running: false,
    preRun: function () {
        Module["addRunDependency"]("isle");
        Module.running = true;
    },
    canvas: (function () {
        return document.getElementById('canvas');
    })(),
    onExit: function () {
        window.location.reload();
    }
};

document.addEventListener('DOMContentLoaded', function () {
    // --- Elements ---
    const audio = document.getElementById('install-audio');
    const soundToggleEmoji = document.getElementById('sound-toggle-emoji');
    const mainContainer = document.getElementById('main-container');
    const topContent = document.getElementById('top-content');
    const controlsWrapper = document.getElementById('controls-wrapper');
    const allPages = document.querySelectorAll('.page-content');
    const pageButtons = document.querySelectorAll('[data-target]');
    const backButtons = document.querySelectorAll('.page-back-button');
    const languageSelect = document.getElementById('language-select');
    const installBtn = document.getElementById('install-btn');
    const uninstallBtn = document.getElementById('uninstall-btn');
    const controlsContainer = document.querySelector('.offline-play-controls');
    const msaaSelect = document.querySelector('select[name="MSAA"]');
    const msaaGroup = msaaSelect.closest('.form-group');
    const afSelect = document.querySelector('select[name="Anisotropic"]');
    const afGroup = afSelect.closest('.form-group');
    const rendererSelect = document.getElementById('renderer-select');
    const hdTextures = document.getElementById('check-hd-textures');
    const hdMusic = document.getElementById('check-hd-music');
    const widescreenBgs = document.getElementById('check-widescreen-bgs');
    const outroFmv = document.getElementById('check-outro');
    const badEnding = document.getElementById('check-ending');
    const logo = document.getElementById('island-logo-img');

    // --- Debug Mode Activation (5 taps on logo) ---
    let debugTapCount = 0;
    let debugTapTimeout = null;
    let debugEnabled = false;

    // Pizza celebration animation for OGEL mode
    function celebratePizza(originElement) {
        const rect = originElement.getBoundingClientRect();
        const centerX = rect.left + rect.width / 2;
        const centerY = rect.top + rect.height / 2;
        const sliceCount = 12;

        for (let i = 0; i < sliceCount; i++) {
            const slice = document.createElement('div');
            slice.className = 'pizza-slice';
            slice.textContent = '🍕';

            // Calculate direction for this slice
            const angle = (i / sliceCount) * Math.PI * 2;
            const distance = 150 + Math.random() * 100;
            const tx = Math.cos(angle) * distance;
            const ty = Math.sin(angle) * distance;
            const rotation = (Math.random() - 0.5) * 720;

            slice.style.left = centerX + 'px';
            slice.style.top = centerY + 'px';
            slice.style.setProperty('--tx', tx + 'px');
            slice.style.setProperty('--ty', ty + 'px');
            slice.style.setProperty('--rot', rotation + 'deg');
            slice.style.animationDelay = (Math.random() * 0.2) + 's';

            document.body.appendChild(slice);

            // Remove after animation completes
            setTimeout(function() {
                slice.remove();
            }, 1700);
        }
    }

    logo.addEventListener('click', function() {
        if (debugEnabled) {
            // Replay pizza animation on subsequent clicks
            celebratePizza(logo);
            return;
        }

        debugTapCount++;
        clearTimeout(debugTapTimeout);

        if (debugTapCount >= 5) {
            // Enable debug mode
            debugEnabled = true;
            logo.src = 'ogel.webp';
            logo.alt = 'OGEL Mode Enabled';

            // Celebrate with pizza!
            celebratePizza(logo);

            // Dynamically load debug.js
            const script = document.createElement('script');
            script.src = 'debug.js';
            document.body.appendChild(script);
        } else {
            // Reset tap count after 1 second of no taps
            debugTapTimeout = setTimeout(function() {
                debugTapCount = 0;
            }, 1000);
        }
    });

    // --- Sound Toggle ---
    function updateSoundEmojiState() {
        soundToggleEmoji.textContent = audio.paused ? '🔇' : '🔊';
        soundToggleEmoji.title = audio.paused ? 'Play Audio' : 'Pause Audio';
    }

    if (audio && soundToggleEmoji) {
        updateSoundEmojiState();
        soundToggleEmoji.addEventListener('click', function () {
            if (audio.paused) {
                audio.currentTime = 0;
                audio.play();
            } else {
                audio.pause();
            }
        });
        audio.addEventListener('play', updateSoundEmojiState);
        audio.addEventListener('pause', updateSoundEmojiState);
    }

    // --- Control Image Hover ---
    const imageControls = document.querySelectorAll('.control-img');
    imageControls.forEach(control => {
        const hoverImage = new Image();
        if (control.dataset.on) {
            hoverImage.src = control.dataset.on;
        }
        control.addEventListener('mouseover', function () { if (this.dataset.on) { this.src = this.dataset.on; } });
        control.addEventListener('mouseout', function () { if (this.dataset.off) { this.src = this.dataset.off; } });
    });

    // --- Emscripten Launch Logic ---
    const runGameButton = document.getElementById('run-game-btn');
    const emscriptenCanvas = document.getElementById('canvas');
    const canvasWrapper = document.getElementById('canvas-wrapper');
    const loadingGifOverlay = document.getElementById('loading-gif-overlay');
    const statusMessageBar = document.getElementById('emscripten-status-message');

    runGameButton.addEventListener('click', function () {
        if (!Module.running) return;
        audio.pause();
        updateSoundEmojiState();
        this.src = this.dataset.on;

        mainContainer.style.display = 'none';
        canvasWrapper.style.display = 'grid';

        document.documentElement.style.overflow = 'hidden';
        document.documentElement.style.overscrollBehavior = 'none';

        Module["disableOffscreenCanvases"] ||= rendererSelect.value == "0 0x682656f3 0x0 0x0 0x2000000";
        console.log("disableOffscreenCanvases: " + Module["disableOffscreenCanvases"]);

        Module["removeRunDependency"]("isle");
        emscriptenCanvas.focus();
    });

    let progressUpdates = 0;
    const debugUI = document.getElementById('debug-ui');
    let debugUIVisible = false;

    // MutationObserver to prevent Emscripten from hiding the debug UI
    const debugUIObserver = new MutationObserver(function(mutations) {
        if (debugUIVisible && debugUI.style.display === 'none') {
            debugUI.style.setProperty('display', 'block', 'important');
        }
    });
    debugUIObserver.observe(debugUI, { attributes: true, attributeFilter: ['style'] });

    emscriptenCanvas.addEventListener('presenterProgress', function (event) {
        // Intro animation is ready
        if (event.detail.objectName == 'Lego_Smk' && event.detail.tickleState == 1) {
            loadingGifOverlay.style.display = 'none';
            emscriptenCanvas.style.setProperty('display', 'block', 'important');
            debugUIVisible = true;
            debugUI.style.setProperty('display', 'block', 'important');
        }
        else if (progressUpdates < 1003) {
            progressUpdates++;
            const percent = (progressUpdates / 1003 * 100).toFixed();
            statusMessageBar.innerHTML = 'Loading LEGO® Island... please wait! <code>' + percent + '%</code>';
        }
    });

    emscriptenCanvas.addEventListener('extensionProgress', function (event) {
        statusMessageBar.innerHTML = 'Loading ' + event.detail.name + '... please wait! <code>' + event.detail.progress + '%</code>';
    });

    // --- Page Navigation Logic ---
    function showPage(pageId, pushState = true) {
        const page = document.querySelector(pageId);
        if (!page) return;

        // Hide main content
        topContent.style.display = 'none';
        controlsWrapper.style.display = 'none';

        // Show selected page
        page.style.display = 'flex';
        window.scroll(0, 0);

        // Reset Read Me tabs to About when entering
        if (pageId === '#read-me-page') {
            document.querySelectorAll('.tab-btn').forEach(btn => {
                btn.classList.toggle('active', btn.dataset.tab === 'about');
            });
            document.querySelectorAll('.tab-panel').forEach(panel => {
                panel.classList.toggle('active', panel.id === 'tab-about');
            });
        }

        if (pushState) {
            const newPath = pageId.replace('-page', '');
            history.pushState({ page: pageId }, '', newPath);
        }
    }

    function showMainMenu() {
        // Hide all pages
        allPages.forEach(p => p.style.display = 'none');

        // Show main content
        topContent.style.display = 'flex';
        controlsWrapper.style.display = 'flex';
    }

    pageButtons.forEach(button => {
        button.addEventListener('click', (e) => {
            const targetId = e.currentTarget.dataset.target;
            showPage(targetId);
        });
    });

    backButtons.forEach(button => {
        button.addEventListener('click', () => {
            history.back();
        });
    });

    // --- Read Me Tabs ---
    const tabButtons = document.querySelectorAll('.tab-btn');
    const tabPanels = document.querySelectorAll('.tab-panel');

    tabButtons.forEach(button => {
        button.addEventListener('click', () => {
            const targetTab = button.dataset.tab;

            // Update button states
            tabButtons.forEach(btn => btn.classList.remove('active'));
            button.classList.add('active');

            // Update panel visibility
            tabPanels.forEach(panel => {
                panel.classList.remove('active');
                if (panel.id === 'tab-' + targetTab) {
                    panel.classList.add('active');
                }
            });
        });
    });

    // --- Configure Tabs ---
    const configTabButtons = document.querySelectorAll('.config-tab-btn');
    const configTabPanels = document.querySelectorAll('.config-tab-panel');

    configTabButtons.forEach(button => {
        button.addEventListener('click', () => {
            const targetTab = button.dataset.configTab;
            configTabButtons.forEach(btn => btn.classList.remove('active'));
            button.classList.add('active');
            configTabPanels.forEach(panel => {
                panel.classList.remove('active');
                if (panel.id === 'config-tab-' + targetTab) {
                    panel.classList.add('active');
                    // Open first section, close others
                    const sections = panel.querySelectorAll('.config-section-card');
                    sections.forEach((section, index) => {
                        section.open = (index === 0);
                    });
                }
            });
        });
    });

    // --- Accordion behavior for config sections ---
    const configSections = document.querySelectorAll('.config-section-card');
    configSections.forEach(section => {
        const summary = section.querySelector('summary');
        if (summary) {
            summary.addEventListener('click', (e) => {
                // If this section is closed and about to open, close others first
                if (!section.open) {
                    configSections.forEach(other => {
                        if (other !== section && other.open) {
                            other.open = false;
                        }
                    });
                }
            });
        }
    });

    // --- Preset Buttons ---
    const presetClassic = document.getElementById('preset-classic');
    const presetModern = document.getElementById('preset-modern');

    function applyPreset(preset) {
        if (preset === 'classic') {
            // Game section defaults
            document.getElementById('language-select').value = 'en';
            document.getElementById('window-windowed').checked = true;
            document.getElementById('aspect-original').checked = true;
            document.getElementById('resolution-original').checked = true;
            // Detail section defaults
            document.getElementById('gfx-high').checked = true;
            document.getElementById('tex-high').checked = true;
            document.getElementById('max-lod').value = '3.6';
            document.getElementById('max-allowed-extras').value = '20';
            // Disable all extensions
            document.getElementById('check-hd-textures').checked = false;
            document.getElementById('check-hd-music').checked = false;
            document.getElementById('check-widescreen-bgs').checked = false;
            document.getElementById('check-outro').checked = false;
            document.getElementById('check-ending').checked = false;
        } else if (preset === 'modern') {
            document.getElementById('aspect-wide').checked = true;
            document.getElementById('resolution-wide').checked = true;
            document.getElementById('gfx-high').checked = true;
            document.getElementById('tex-high').checked = true;
            document.getElementById('max-lod').value = '6';
            document.getElementById('max-allowed-extras').value = '40';
            // Enable HD extensions
            document.getElementById('check-hd-textures').checked = true;
            document.getElementById('check-hd-music').checked = true;
            document.getElementById('check-widescreen-bgs').checked = true;
        }
        // Trigger change event to save config
        const configForm = document.getElementById('config-form');
        if (configForm) {
            configForm.dispatchEvent(new Event('change'));
        }
        // Refresh Offline Play button state
        if (typeof checkInitialCacheStatus === 'function') {
            checkInitialCacheStatus();
        }
    }

    if (presetClassic) {
        presetClassic.addEventListener('click', () => applyPreset('classic'));
    }
    if (presetModern) {
        presetModern.addEventListener('click', () => applyPreset('modern'));
    }

    // --- Config Toast ---
    const configToast = document.getElementById('config-toast');
    let toastTimeout = null;

    function showConfigToast() {
        if (configToast) {
            configToast.classList.add('show');
            if (toastTimeout) clearTimeout(toastTimeout);
            toastTimeout = setTimeout(() => {
                configToast.classList.remove('show');
            }, 2000);
        }
    }

    window.addEventListener('popstate', (e) => {
        if (e.state && e.state.page && e.state.page !== 'main') {
            showPage(e.state.page, false);
        } else {
            showMainMenu();
        }
    });

    // --- OPFS Config Manager ---
    const configManager = {
        form: document.querySelector('.config-form'),
        filePath: 'isle.ini',

        async init() {
            if (!this.form) return;
            await this.loadConfig();
            this.form.addEventListener('change', () => this.saveConfig());
        },

        async getFileHandle() {
            try {
                const root = await navigator.storage.getDirectory();
                return await root.getFileHandle(this.filePath, { create: true });
            } catch (e) {
                console.error("OPFS not available or permission denied.", e);
                document.getElementById('opfs-disabled').style.display = '';
                document.getElementById('config-form').querySelectorAll('input, select').forEach(element => {
                    element.disabled = true;
                });
                return null;
            }
        },

        async saveConfig() {
            // This function now uses an inline Web Worker for maximum compatibility,
            // especially with Safari, which does not support createWritable().

            let iniContent = '[isle]\n';
            const elements = this.form.elements;

            for (const element of elements) {
                if (!element.name || element.dataset.notIni == "true") continue;

                let value;
                switch (element.type) {
                    case 'checkbox':
                        value = element.checked ? 'YES' : 'NO';
                        iniContent += `${element.name}=${value}\n`;
                        break;
                    case 'radio':
                        if (element.checked) {
                            value = element.value;
                            iniContent += `${element.name}=${value}\n`;
                        }
                        break;
                    default:
                        value = element.value;
                        iniContent += `${element.name}=${value}\n`;
                        break;
                }
            }

            iniContent += "[extensions]\n";

            if (hdTextures) {
                value = hdTextures.checked ? 'YES' : 'NO';
                iniContent += `${hdTextures.name}=${value}\n`;
            }

            siFiles = getSiFiles();
            if (siFiles.length > 0 || outroFmv.checked) {
                iniContent += `SI Loader=YES\n`;
                iniContent += "[si loader]\n";
            }

            if (siFiles.length > 0) {
                iniContent += `files=${siFiles.join(',')}\n`;
            }

            let directives = [];

            if (outroFmv.checked) {
                directives = directives.concat([
                    "FullScreenMovie:\\lego\\scripts\\intro:3",
                    "Disable3d:\\lego\\scripts\\credits:499",
                    "Prepend:\\lego\\scripts\\intro:3:\\lego\\scripts\\credits:499",
                    "RemoveWith:\\lego\\scripts\\credits:499:\\lego\\scripts\\intro:3"
                ]);
            }

            if (directives.length > 0) {
                iniContent += `directives=${directives.join(",\\\n")}\n`;
            }

            const workerCode = `
                        self.onmessage = async (e) => {
                            if (e.data.action === 'save') {
                                try {
                                    const root = await navigator.storage.getDirectory();
                                    const handle = await root.getFileHandle(e.data.filePath, { create: true });
                                    const accessHandle = await handle.createSyncAccessHandle();
                                    const encoder = new TextEncoder();
                                    const encodedData = encoder.encode(e.data.content);

                                    accessHandle.truncate(0);
                                    accessHandle.write(encodedData, { at: 0 });
                                    accessHandle.flush();
                                    accessHandle.close();

                                    self.postMessage({ status: 'success', message: 'Config saved to ' + e.data.filePath });
                                } catch (err) {
                                    self.postMessage({ status: 'error', message: 'Failed to save config: ' + err.message });
                                }
                            }
                        };
                    `;

            const blob = new Blob([workerCode], { type: 'application/javascript' });
            const workerUrl = URL.createObjectURL(blob);
            const worker = new Worker(workerUrl);

            worker.postMessage({
                action: 'save',
                content: iniContent,
                filePath: this.filePath
            });

            worker.onmessage = (e) => {
                console.log(e.data.message);
                URL.revokeObjectURL(workerUrl); // Clean up the temporary URL
                worker.terminate();
                if (e.data.status === 'success') {
                    showConfigToast();
                }
            };

            worker.onerror = (e) => {
                console.error('An error occurred in the config-saving worker:', e.message);
                URL.revokeObjectURL(workerUrl);
                worker.terminate();
            };
        },

        async loadConfig() {
            const handle = await this.getFileHandle();
            if (!handle) return;

            const file = await handle.getFile();
            const text = await file.text();
            if (!text) {
                console.log('No existing config file found, using defaults.');
                await this.saveConfig();
                return;
            }

            const config = {};
            const lines = text.split('\n');
            for (const line of lines) {
                if (line.startsWith('[') || !line.includes('=')) continue;
                const [key, ...valueParts] = line.split('=');
                const value = valueParts.join('=').trim();
                config[key.trim()] = value;
            }

            this.applyConfigToForm(config);
            console.log('Config loaded from', this.filePath);
        },

        applyConfigToForm(config) {
            const elements = this.form.elements;
            for (const key in config) {
                if (key == "files") {
                    elements["HD Music"].checked = config[key].includes("hdmusic.si");
                    elements["Widescreen Backgrounds"].checked = config[key].includes("widescreen.si");
                    elements["Extended Bad Ending FMV"].checked = config[key].includes("badend.si");
                    continue;
                }

                if (key == "directives") {
                    elements["Outro FMV"].checked = config[key].includes("intro:3");
                    continue;
                }

                const element = elements[key];
                if (!element) continue;

                const value = config[key];

                if (element.type === 'checkbox') {
                    element.checked = (value === 'YES');
                } else if (element.nodeName === 'RADIO') { // radio nodelist
                    for (const radio of element) {
                        if (radio.value === value) {
                            radio.checked = true;
                            break;
                        }
                    }
                }
                else {
                    element.value = value;
                }
            }
        }
    };

    // Handle initial page load with a hash
    const initialHash = window.location.hash;
    if (initialHash) {
        const initialPageId = initialHash + '-page';
        if (document.querySelector(initialPageId)) {
            const urlPath = window.location.pathname;
            history.replaceState({ page: 'main' }, '', urlPath);
            showPage(initialPageId, true);
        }
    } else {
        history.replaceState({ page: 'main' }, '', window.location.pathname);
    }

    if (document.documentElement.requestFullscreen) {
        const fullscreenElement = document.getElementById('window-fullscreen');
        const windowedElement = document.getElementById('window-windowed');

        fullscreenElement.addEventListener('change', () => {
            if (fullscreenElement.checked) {
                document.documentElement.requestFullscreen().catch(err => {
                    console.error(`Error attempting to enable full-screen mode: ${err.message} (${err.name})`);
                });
            }
        });

        windowedElement.addEventListener('change', () => {
            if (windowedElement.checked && document.fullscreenElement) {
                document.exitFullscreen();
            }
        });

        // Event listener for changes in fullscreen state (e.g., F11 or Esc key)
        document.addEventListener('fullscreenchange', () => {
            if (document.fullscreenElement) {
                fullscreenElement.checked = true;
            } else {
                windowedElement.checked = true;
            }
        });
    }
    else {
        document.getElementById('window-form').style.display = 'none';
    }

    if (!window.matchMedia('(any-pointer: coarse)').matches) {
        document.getElementById('touch-section').style.display = 'none';
    }

    const gl = document.createElement('canvas').getContext('webgl2');
    if (gl) {
        const samples = gl.getInternalformatParameter(gl.RENDERBUFFER, gl.RGBA8, gl.SAMPLES);
        if (samples && samples.length > 0 && Math.max(...samples) > 1) {
            msaaSelect.innerHTML = '';
            const offOption = document.createElement('option');
            offOption.value = '1';
            offOption.textContent = 'Off';
            msaaSelect.appendChild(offOption);
            samples.sort().forEach(sampleCount => {
                if (sampleCount > 1) {
                    const option = document.createElement('option');
                    option.value = sampleCount;
                    option.textContent = `${sampleCount}x`;
                    msaaSelect.appendChild(option);
                }
            });
        } else {
            msaaGroup.style.display = 'none';
        }

        const ext = gl.getExtension('EXT_texture_filter_anisotropic');
        if (ext) {
            const maxAnisotropy = gl.getParameter(ext.MAX_TEXTURE_MAX_ANISOTROPY_EXT);

            afSelect.innerHTML = '';

            const offOption = document.createElement('option');
            offOption.value = '1';
            offOption.textContent = 'Off';
            afSelect.appendChild(offOption);

            const defaultAniso = Math.min(maxAnisotropy, 16);

            for (let i = 2; i <= maxAnisotropy; i *= 2) {
                const option = document.createElement('option');
                option.value = i;
                option.textContent = `${i}x`;
                option.selected = defaultAniso == i;
                afSelect.appendChild(option);
            }
        } else {
            afGroup.style.display = 'none';
        }
    } else {
        msaaGroup.style.display = 'none';
        afGroup.style.display = 'none';
    }

    let downloaderWorker = null;
    let missingGameFiles = [];

    // Update popup elements
    const updatePopup = document.getElementById('update-popup');
    const updateReloadBtn = document.getElementById('update-reload-btn');
    const updateDismissBtn = document.getElementById('update-dismiss-btn');

    function showUpdatePopup() {
        if (updatePopup) {
            updatePopup.style.display = 'flex';
        }
    }

    function hideUpdatePopup() {
        if (updatePopup) {
            updatePopup.style.display = 'none';
        }
    }

    if (updateReloadBtn) {
        updateReloadBtn.addEventListener('click', () => {
            window.location.reload();
        });
    }

    if (updateDismissBtn) {
        updateDismissBtn.addEventListener('click', () => {
            hideUpdatePopup();
        });
    }

    // Goodbye popup elements
    const goodbyePopup = document.getElementById('goodbye-popup');
    const goodbyeCancelBtn = document.getElementById('goodbye-cancel-btn');
    const goodbyeProgressBar = document.querySelector('.goodbye-progress-bar');
    const cancelBtn = document.getElementById('cancel-btn');
    let goodbyeTimeout = null;
    let goodbyeInterval = null;

    function showGoodbyePopup() {
        if (goodbyePopup && goodbyePopup.style.display !== 'flex') {
            goodbyePopup.style.display = 'flex';
            if (goodbyeProgressBar) {
                goodbyeProgressBar.style.width = '0%';
            }
            startGoodbyeCountdown();
        }
    }

    function hideGoodbyePopup() {
        if (goodbyePopup) {
            goodbyePopup.style.display = 'none';
        }
        if (goodbyeTimeout) {
            clearTimeout(goodbyeTimeout);
            goodbyeTimeout = null;
        }
        if (goodbyeInterval) {
            clearInterval(goodbyeInterval);
            goodbyeInterval = null;
        }
    }

    function startGoodbyeCountdown() {
        const duration = 4000;
        const startTime = Date.now();

        goodbyeInterval = setInterval(() => {
            const elapsed = Date.now() - startTime;
            const progress = Math.min(elapsed / duration, 1);
            if (goodbyeProgressBar) {
                goodbyeProgressBar.style.width = (progress * 100) + '%';
            }
            if (progress >= 1) {
                clearInterval(goodbyeInterval);
            }
        }, 50);

        goodbyeTimeout = setTimeout(() => {
            window.location.href = 'https://legoisland.org';
        }, duration);
    }

    if (cancelBtn) {
        cancelBtn.addEventListener('click', showGoodbyePopup);
    }

    if (goodbyeCancelBtn) {
        goodbyeCancelBtn.addEventListener('click', hideGoodbyePopup);
    }

    if ('serviceWorker' in navigator) {
        Promise.all([
            configManager.init(),
            navigator.serviceWorker.register('/sw.js').then(() => navigator.serviceWorker.ready)
        ]).then(([configResult, swRegistration]) => {
            checkInitialCacheStatus();
            showOrHideGraphicsOptions();

            // Check if there's already a waiting service worker (update ready)
            if (swRegistration.waiting) {
                showUpdatePopup();
            }

            // Listen for new service worker updates
            swRegistration.addEventListener('updatefound', () => {
                const newWorker = swRegistration.installing;
                if (newWorker) {
                    newWorker.addEventListener('statechange', () => {
                        // When the new worker is installed and waiting, show the update popup
                        // Only show if there's an existing controller (this is an update, not first install)
                        if (newWorker.state === 'installed' && navigator.serviceWorker.controller) {
                            showUpdatePopup();
                        }
                    });
                }
            });
        }).catch(error => {
            console.error('Initialization failed:', error);
        });

        navigator.serviceWorker.addEventListener('message', handleServiceWorkerMessage);
        navigator.serviceWorker.addEventListener('controllerchange', () => {
            checkInitialCacheStatus();
        });
    }
    else {
        configManager.init().then(() => {
            showOrHideGraphicsOptions();
        });
    }

    const progressCircular = document.createElement('div');
    progressCircular.className = 'progress-circular';
    controlsContainer.appendChild(progressCircular);

    installBtn.addEventListener('click', async () => {
        if (navigator.serviceWorker && navigator.serviceWorker.controller) {
            await requestPersistentStorage();

            if (downloaderWorker) downloaderWorker.terminate();
            downloaderWorker = new Worker('/downloader.js');
            downloaderWorker.onmessage = handleWorkerMessage;

            const selectedLanguage = languageSelect.value;
            installBtn.style.display = 'none';
            uninstallBtn.style.display = 'none';
            progressCircular.style.display = 'flex';
            progressCircular.textContent = '0%';
            progressCircular.style.background = 'conic-gradient(#FFD700 0deg, #333 0deg)';

            downloaderWorker.postMessage({
                action: 'install',
                missingFiles: missingGameFiles,
                language: selectedLanguage
            });
        }
    });

    uninstallBtn.addEventListener('click', () => {
        const selectedLanguage = languageSelect.value;
        navigator.serviceWorker.controller.postMessage({
            action: 'uninstall_language_pack',
            language: selectedLanguage
        });
    });

    languageSelect.addEventListener('change', () => {
        checkInitialCacheStatus();
    });

    hdTextures.addEventListener('change', () => {
        checkInitialCacheStatus();
    });

    hdMusic.addEventListener('change', () => {
        checkInitialCacheStatus();
    });

    widescreenBgs.addEventListener('change', () => {
        checkInitialCacheStatus();
    });

    badEnding.addEventListener('change', () => {
        checkInitialCacheStatus();
    });

    rendererSelect.addEventListener('change', () => {
        showOrHideGraphicsOptions();
    });

    async function requestPersistentStorage() {
        if (navigator.storage && navigator.storage.persist) {
            const isPersisted = await navigator.storage.persisted();
            if (!isPersisted) {
                const wasGranted = await navigator.storage.persist();
                if (wasGranted) {
                    console.log('Persistent storage was granted.');
                } else {
                    console.log('Persistent storage request was denied.');
                }
            }
        }
    }

    function getSiFiles() {
        siFiles = [];
        if (hdMusic && hdMusic.checked) {
            siFiles.push('/LEGO/extra/hdmusic.si');
        }
        if (widescreenBgs && widescreenBgs.checked) {
            siFiles.push('/LEGO/extra/widescreen.si');
        }
        if (badEnding && badEnding.checked) {
            siFiles.push('/LEGO/extra/badend.si');
        }
        return siFiles;
    }

    function checkInitialCacheStatus() {
        if (navigator.serviceWorker.controller) {
            navigator.serviceWorker.controller.postMessage({
                action: 'check_cache_status',
                language: languageSelect.value,
                hdTextures: hdTextures.checked,
                siFiles: getSiFiles(),
            });
        }
    }

    function showOrHideGraphicsOptions() {
        if (rendererSelect.value == "0 0x682656f3 0x0 0x0 0x2000000") {
            msaaGroup.style.display = 'none';
            afGroup.style.display = 'none';
        }
        else {
            msaaGroup.style.display = '';
            afGroup.style.display = '';
        }
    }

    function updateInstallUI(isInstalled, inProgress = false) {
        progressCircular.style.display = inProgress ? 'flex' : 'none';
        installBtn.style.display = !isInstalled && !inProgress ? 'block' : 'none';
        uninstallBtn.style.display = isInstalled && !inProgress ? 'block' : 'none';
    }

    function handleServiceWorkerMessage(event) {
        const { action, language, isInstalled, success } = event.data;
        if (language && language !== languageSelect.value) return;

        switch (action) {
            case 'cache_status':
                missingGameFiles = event.data.missingFiles;
                updateInstallUI(isInstalled);
                break;
            case 'uninstall_complete':
                updateInstallUI(!success);
                checkInitialCacheStatus();
                break;
        }
    }

    function handleWorkerMessage(event) {
        const { action, progress, success, error } = event.data;

        switch (action) {
            case 'install_progress':
                updateInstallUI(false, true);
                const angle = (progress / 100) * 360;
                progressCircular.textContent = `${Math.round(progress)}%`;
                progressCircular.style.background = `radial-gradient(#181818 60%, transparent 61%), conic-gradient(#FFD700 ${angle}deg, #333 ${angle}deg)`;
                break;
            case 'install_complete':
                updateInstallUI(success);
                if (downloaderWorker) downloaderWorker.terminate();
                break;
            case 'install_failed':
                alert(`Download failed: ${error}`);
                updateInstallUI(false);
                if (downloaderWorker) downloaderWorker.terminate();
                break;
        }
    }
});
