class OverlayManager {
    constructor() {
        this.overlayData = {};
        this.pendingUpdates = [];
        this.webChannelReady = false;

        // Detect VirtualBox environment
        this.isVirtualBox = this.detectVirtualBox();
        if (this.isVirtualBox) {
            console.warn('VIRTUALBOX DETECTED: Overlay may have compatibility issues');
            console.warn('Common VirtualBox overlay problems:');
            console.warn('1. GPU acceleration disabled');
            console.warn('2. WebGL not available');
            console.warn('3. Qt WebEngine software rendering fallback');
            console.warn('4. Transparency effects may fail');
            console.warn('5. WebChannel communication may be unreliable');
        }

        this.initWebChannel();
        this.initCanvas();
    }

    detectVirtualBox() {
        // Check for VirtualBox-specific indicators
        try {
            // Check user agent for VirtualBox
            if (navigator.userAgent && navigator.userAgent.includes('VirtualBox')) {
                return true;
            }

            // Check for VirtualBox-specific plugins or extensions
            if (navigator.plugins) {
                for (let i = 0; i < navigator.plugins.length; i++) {
                    if (navigator.plugins[i].name && navigator.plugins[i].name.includes('VirtualBox')) {
                        return true;
                    }
                }
            }

            // Check for VirtualBox guest additions in renderer info
            const canvas = document.createElement('canvas');
            const gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
            if (gl) {
                const renderer = gl.getParameter(gl.RENDERER);
                if (renderer && (renderer.includes('VirtualBox') || renderer.includes('VBox'))) {
                    return true;
                }
            }

            // Check for Mesa software rendering (common in VirtualBox)
            if (gl) {
                const vendor = gl.getParameter(gl.VENDOR);
                const renderer = gl.getParameter(gl.RENDERER);
                if ((vendor && vendor.includes('Mesa')) ||
                    (renderer && (renderer.includes('Software') || renderer.includes('Mesa')))) {
                    console.warn('MESA SOFTWARE RENDERING DETECTED - likely VirtualBox environment');
                    return true;
                }
            }

            return false;
        } catch (e) {
            console.debug('VirtualBox detection failed:', e);
            return false;
        }
    }

    initWebChannel() {
        try {
            console.log('OVERLAY: Starting WebChannel initialization');
            console.log('OVERLAY: VirtualBox detected:', this.isVirtualBox);

            if (this.isVirtualBox) {
                console.warn('VIRTUALBOX: WebChannel initialization - potential communication issues');
            }

            // Log browser/environment information
            console.log('OVERLAY: Browser environment check:');
            console.log('  - User agent:', navigator.userAgent);
            console.log('  - Platform:', navigator.platform);
            console.log('  - Cookie enabled:', navigator.cookieEnabled);
            console.log('  - OnLine:', navigator.onLine);
            console.log('  - Qt object available:', typeof Qt !== 'undefined');
            console.log('  - qt object available:', typeof qt !== 'undefined');
            console.log('  - QWebChannel available:', typeof QWebChannel !== 'undefined');

            // Wait for DOM to be fully loaded
            this.waitForFullInitialization(() => {
                console.log('OVERLAY: DOM fully loaded, checking Qt WebChannel transport');

                // Check if Qt WebChannel transport is available (set by QWebEnginePage.setWebChannel)
                if (typeof qt !== 'undefined' && qt.webChannelTransport) {
                    console.log('OVERLAY: Qt WebChannel transport available, initializing channel');

                    // Use the transport provided by Qt WebEngine
                    new QWebChannel(qt.webChannelTransport, (channel) => {
                        console.log('OVERLAY: QWebChannel created successfully');

                        // Connect to overlay object
                        window.overlay = channel.objects.overlay;
                        console.log('OVERLAY: Connected to overlay object:', !!window.overlay);

                        if (this.isVirtualBox) {
                            console.warn('VIRTUALBOX: WebChannel connected - testing communication reliability');
                        }

                        // Flush any buffered console messages
                        if (window.flushConsoleBuffer) {
                            window.flushConsoleBuffer();
                        }

                        // Connect signals if overlay object exists
                        if (window.overlay) {
                            console.log('OVERLAY: Setting up signal connections');

                            // Connect positionChanged signal
                            if (window.overlay.positionChanged) {
                                window.overlay.positionChanged.connect((position, duration) => {
                                    console.log('OVERLAY: positionChanged signal received:', position, duration);
                                    if (position !== null && duration !== null) {
                                        this.updateProgress(position, duration);
                                    } else {
                                        console.warn('positionChanged signal received null/undefined parameters, skipping');
                                    }
                                });
                                console.log('OVERLAY: positionChanged signal connected');
                            } else {
                                console.warn('OVERLAY: positionChanged signal not available');
                            }

                            // Connect videoInfoChanged signal
                            if (window.overlay.videoInfoChanged) {
                                window.overlay.videoInfoChanged.connect((info) => {
                                    console.log('OVERLAY: videoInfoChanged signal received:', info);
                                    if (info && typeof info === 'object') {
                                        this.updateVideoInfo(info);
                                    } else {
                                        console.warn('videoInfoChanged signal received null/undefined parameter, skipping');
                                    }
                                });
                                console.log('OVERLAY: videoInfoChanged signal connected');
                            } else {
                                console.warn('OVERLAY: videoInfoChanged signal not available');
                            }

                            // Connect dataUpdated signal for templates that need it (like results.html)
                            if (window.overlay.dataUpdated) {
                                window.overlay.dataUpdated.connect((data) => {
                                    console.log('OVERLAY: dataUpdated signal received:', data);
                                    if (data !== null && data !== undefined) {
                                        // Call a global callback if it exists (for results.html and other templates)
                                        if (window.onDataUpdated) {
                                            window.onDataUpdated(data);
                                        }
                                        console.log('dataUpdated signal processed');
                                    } else {
                                        console.warn('dataUpdated signal received null/undefined data');
                                    }
                                });
                                console.log('OVERLAY: dataUpdated signal connected');
                            } else {
                                console.warn('OVERLAY: dataUpdated signal not available');
                            }

                            // Test WebChannel communication
                            this.testWebChannelCommunication();

                            // Mark WebChannel as ready
                            this.webChannelReady = true;
                            console.log('OVERLAY: WebChannel fully initialized and ready');

                            // Process pending updates after full initialization
                            setTimeout(() => this.processPendingUpdates(), 100);
                            console.log('WebChannel connected and ready');
                        } else {
                            console.error('OVERLAY: Overlay object not found in WebChannel');
                            if (this.isVirtualBox) {
                                console.error('VIRTUALBOX: WebChannel object missing - communication setup failed');
                            }
                        }
                    });
                } else {
                    console.warn('OVERLAY: Qt WebChannel transport not available, falling back to QtWebChannel constructor');
                    if (this.isVirtualBox) {
                        console.warn('VIRTUALBOX: Primary WebChannel transport failed, trying fallback');
                    }

                    // Fallback: try the old method
                    if (typeof Qt === 'object' && typeof QtWebChannel === 'function') {
                        console.log('OVERLAY: Using QtWebChannel fallback method');
                        const channel = new QtWebChannel();
                        channel.connectTo('overlay', (overlay) => {
                            console.log('OVERLAY: Fallback WebChannel connected');
                            window.overlay = overlay;

                            // Connect signals (same as above)
                            if (overlay.positionChanged) {
                                overlay.positionChanged.connect((position, duration) => {
                                    console.log('OVERLAY: [FALLBACK] positionChanged signal received:', position, duration);
                                    if (position !== null && duration !== null) {
                                        this.updateProgress(position, duration);
                                    } else {
                                        console.warn('positionChanged signal received null/undefined parameters, skipping');
                                    }
                                });
                            }

                            if (overlay.videoInfoChanged) {
                                overlay.videoInfoChanged.connect((info) => {
                                    console.log('OVERLAY: [FALLBACK] videoInfoChanged signal received:', info);
                                    if (info && typeof info === 'object') {
                                        this.updateVideoInfo(info);
                                    } else {
                                        console.warn('videoInfoChanged signal received null/undefined parameter, skipping');
                                    }
                                });
                            }

                            if (overlay.dataUpdated) {
                                overlay.dataUpdated.connect((data) => {
                                    console.log('OVERLAY: [FALLBACK] dataUpdated signal received:', data);
                                    if (data !== null && data !== undefined) {
                                        if (window.onDataUpdated) {
                                            window.onDataUpdated(data);
                                        }
                                        console.log('dataUpdated signal processed');
                                    } else {
                                        console.warn('dataUpdated signal received null/undefined data');
                                    }
                                });
                            }

                            // Test WebChannel communication
                            this.testWebChannelCommunication();

                            // Mark WebChannel as ready
                            this.webChannelReady = true;

                            // Process pending updates after full initialization
                            setTimeout(() => this.processPendingUpdates(), 100);
                            console.log('WebChannel connected via fallback method');
                        });
                    } else {
                        console.error('OVERLAY: QtWebChannel not available either');
                        if (this.isVirtualBox) {
                            console.error('VIRTUALBOX: Both WebChannel methods failed - overlays will not work');
                        }
                        // Retry with exponential backoff
                        setTimeout(() => this.initWebChannel(), 1000);
                    }
                }
            });
        } catch (error) {
            console.error('OVERLAY: WebChannel initialization error:', error);
            if (this.isVirtualBox) {
                console.error('VIRTUALBOX: WebChannel initialization failed - overlays disabled');
            }
            // Retry with exponential backoff
            setTimeout(() => this.initWebChannel(), 1000);
        }
    }

    testWebChannelCommunication() {
        try {
            console.log('OVERLAY: Testing WebChannel communication');

            if (window.overlay && window.overlay.log) {
                // Test basic communication
                window.overlay.log('OVERLAY: WebChannel communication test - basic log message');

                // Test data retrieval if available
                if (window.overlay.getCurrentData) {
                    window.overlay.getCurrentData().then(result => {
                        console.log('OVERLAY: WebChannel data retrieval test successful:', result);
                    }).catch(error => {
                        console.error('OVERLAY: WebChannel data retrieval test failed:', error);
                        if (this.isVirtualBox) {
                            console.error('VIRTUALBOX: WebChannel data retrieval failed - communication unreliable');
                        }
                    });
                }

                console.log('OVERLAY: WebChannel communication test completed');
            } else {
                console.error('OVERLAY: Cannot test WebChannel - overlay object or log method missing');
            }
        } catch (error) {
            console.error('OVERLAY: WebChannel communication test failed:', error);
        }
    }

    waitForFullInitialization(callback) {
        const checkReady = () => {
            if (document.readyState === 'complete' && this.validateCriticalElements()) {
                callback();
            } else {
                setTimeout(checkReady, 100);
            }
        };
        checkReady();
    }

    processPendingUpdates() {
        // Prevent infinite loops by limiting processing attempts
        let processed = 0;
        const maxProcessing = 10;
        
        while (this.pendingUpdates.length > 0 && processed < maxProcessing) {
            // Double-check readiness before processing pending update
            if (!this.isSystemReady()) {
                console.log('System not ready during pending updates processing');
                break;
            }
            
            const update = this.pendingUpdates.shift();
            // Add null check before processing pending update
            if (update && typeof update === 'object') {
                this.updateOverlay(update);
                processed++;
            } else {
                console.warn('Skipping null/invalid pending update:', update);
                processed++;
            }
        }
        
        // If there are still pending updates, schedule another processing cycle
        if (this.pendingUpdates.length > 0) {
            setTimeout(() => this.processPendingUpdates(), 300);
        }
    }

    updateOverlay(data) {
        // Comprehensive null/undefined check for data parameter
        if (!data) {
            console.warn('updateOverlay called with null/undefined data');
            console.warn('Call stack:', new Error().stack);
            return;
        }
        
        console.log('Updating overlay with data:', data);
        
        // Enhanced readiness check with multiple validation layers
        if (!this.isSystemReady()) {
            console.log('System not ready, queuing update');
            this.pendingUpdates.push(data);
            // Retry with progressive backoff
            setTimeout(() => this.processPendingUpdates(), 150);
            return;
        }
        
        // Validate all critical elements exist before any updates
        if (!this.validateCriticalElements()) {
            console.warn('Critical elements not available, requeueing update');
            this.pendingUpdates.push(data);
            setTimeout(() => this.processPendingUpdates(), 200);
            return;
        }
        
        this.overlayData = { ...this.overlayData, ...data };
        
        // Update title elements with safe element access
        // Additional null check for data.title
        if (data.hasOwnProperty('title') && data.title !== undefined && data.title !== null) {
            if (!this.safeUpdateElement('titleMain', data.title, 'textContent')) {
                console.warn('Failed to update titleMain, queuing for retry');
                this.pendingUpdates.push({title: data.title});
                return;
            }
        }
        
        // Additional null check for data.subtitle
        if (data.hasOwnProperty('subtitle') && data.subtitle !== undefined && data.subtitle !== null) {
            if (!this.safeUpdateElement('titleSubtitle', data.subtitle, 'textContent')) {
                console.warn('Failed to update titleSubtitle, queuing for retry');
                this.pendingUpdates.push({subtitle: data.subtitle});
                return;
            }
        }
        
        // Update ticker text with null check
        if (data.hasOwnProperty('ticker') && data.ticker !== undefined && data.ticker !== null) {
            if (!this.safeUpdateElement('tickerText', data.ticker, 'textContent')) {
                console.warn('Failed to update tickerText, queuing for retry');
                this.pendingUpdates.push({ticker: data.ticker});
                return;
            }
        }
        
        // Show/hide stats panel with null check
        if (data.hasOwnProperty('showStats') && data.showStats !== undefined && data.showStats !== null) {
            if (!this.safeUpdateElement('statsPanel', data.showStats ? 'block' : 'none', 'display')) {
                console.warn('Failed to update statsPanel, queuing for retry');
                this.pendingUpdates.push({showStats: data.showStats});
                return;
            }
        }
        
        // Update custom CSS if provided with null check
        if (data.hasOwnProperty('customCSS') && data.customCSS !== undefined && data.customCSS !== null) {
            this.applyCustomCSS(data.customCSS);
        }
    }

    isSystemReady() {
        try {
            return this.webChannelReady &&
                   document.readyState === 'complete' &&
                   document.getElementById('titleMain') !== null &&
                   document.body !== null;
        } catch (error) {
            console.warn('Error in isSystemReady check:', error);
            return false;
        }
    }

    validateCriticalElements() {
        try {
            const criticalIds = ['titleMain', 'titleSubtitle', 'tickerText', 'statsPanel', 'progressBar'];
            
            for (const id of criticalIds) {
                const element = document.getElementById(id);
                if (!element) {
                    console.warn(`Critical element ${id} not found`);
                    return false;
                }
                // Additional check for element validity
                if (element.parentNode === null || !document.contains(element)) {
                    console.warn(`Critical element ${id} not properly attached to DOM`);
                    return false;
                }
            }
            return true;
        } catch (error) {
            console.warn('Error in validateCriticalElements:', error);
            return false;
        }
    }

    safeUpdateElement(elementId, value, property = 'textContent') {
        // Null check for elementId parameter
        if (elementId === null || elementId === undefined) {
            console.warn('safeUpdateElement called with null/undefined elementId');
            return false;
        }
        
        // For textContent property, convert null/undefined to empty string
        if (property === 'textContent' && (value === null || value === undefined)) {
            value = '';
        }
        
        // For other properties, null/undefined values are not allowed
        if (property !== 'textContent' && (value === null || value === undefined)) {
            console.warn(`safeUpdateElement called with null/undefined value for property ${property}`);
            return false;
        }
        
        try {
            const element = document.getElementById(elementId);
            if (!element) {
                console.warn(`Element ${elementId} not found`);
                return false;
            }
            
            // Double-check element is still valid and in DOM
            if (element.parentNode === null) {
                console.warn(`Element ${elementId} no longer in DOM`);
                return false;
            }
            
            // Additional check for element accessibility
            if (!document.contains(element)) {
                console.warn(`Element ${elementId} not contained in document`);
                return false;
            }
            
            if (property === 'display') {
                element.style.display = value;
            } else if (property === 'width') {
                element.style.width = value;
            } else if (property === 'textContent') {
                // Check if textContent property exists and is writable
                if ('textContent' in element) {
                    element.textContent = value;
                    // Animate only if element update succeeded
                    this.animateElement(elementId, 'pulse');
                } else {
                    console.warn(`Element ${elementId} does not support textContent`);
                    return false;
                }
            }
            
            return true;
        } catch (error) {
            console.error(`Error updating element ${elementId}:`, error);
            return false;
        }
    }

    updateProgress(position, duration) {
        // Null checks for position and duration parameters
        if (position === null || position === undefined) {
            console.warn('updateProgress called with null/undefined position');
            return;
        }
        
        if (duration === null || duration === undefined) {
            console.warn('updateProgress called with null/undefined duration');
            return;
        }
        
        try {
            // Check system readiness before updating progress
            if (!this.isSystemReady()) {
                console.log('System not ready for progress update, skipping');
                return;
            }
            
            const percentage = duration > 0 ? (position / duration) * 100 : 0;
            
            // Safe progress bar update
            this.safeUpdateElement('progressBar', `${percentage}%`, 'width');
            
        } catch (error) {
            console.error('Error updating progress:', error);
        }
    }

    updateVideoInfo(info) {
        // Comprehensive null/undefined check for info parameter
        if (!info) {
            console.warn('updateVideoInfo called with null/undefined info');
            return;
        }
        
        console.log('Video info updated:', info);
        
        if (info.hasOwnProperty('resolution') && info.resolution !== undefined && info.resolution !== null) {
            const resolutionElement = document.getElementById('resolution');
            if (resolutionElement) {
                resolutionElement.textContent = info.resolution;
            }
        }
        if (info.hasOwnProperty('bitrate') && info.bitrate !== undefined && info.bitrate !== null) {
            const bitrateElement = document.getElementById('bitrate');
            if (bitrateElement) {
                bitrateElement.textContent = info.bitrate;
            }
        }
        if (info.hasOwnProperty('codec') && info.codec !== undefined && info.codec !== null) {
            const codecElement = document.getElementById('codec');
            if (codecElement) {
                codecElement.textContent = info.codec;
            }
        }
        if (info.hasOwnProperty('fps') && info.fps !== undefined && info.fps !== null) {
            const fpsElement = document.getElementById('fps');
            if (fpsElement) {
                fpsElement.textContent = info.fps;
            }
        }
    }

    formatTime(seconds) {
        const mins = Math.floor(seconds / 60);
        const secs = Math.floor(seconds % 60);
        return `${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
    }

    animateElement(elementId, animationClass) {
        // Null checks for elementId and animationClass parameters
        if (elementId === null || elementId === undefined) {
            console.warn('animateElement called with null/undefined elementId');
            return;
        }
        
        if (animationClass === null || animationClass === undefined) {
            console.warn('animateElement called with null/undefined animationClass');
            return;
        }
        
        const element = document.getElementById(elementId);
        if (element) {
            element.style.animation = 'none';
            element.offsetHeight; // Trigger reflow
            element.style.animation = `${animationClass} 1s ease-in-out`;
        }
    }

    applyCustomCSS(css) {
        let styleElement = document.getElementById('customStyles');
        if (!styleElement) {
            styleElement = document.createElement('style');
            styleElement.id = 'customStyles';
            document.head.appendChild(styleElement);
        }
        styleElement.textContent = css;
    }

    initCanvas() {
        console.log('OVERLAY: Initializing canvas for diagnostics');

        this.canvas = document.getElementById('canvasOverlay');
        this.ctx = this.canvas ? this.canvas.getContext('2d') : null;
        this.animationFrame = null;

        console.log('OVERLAY: Canvas element found:', !!this.canvas);
        console.log('OVERLAY: Canvas 2D context available:', !!this.ctx);

        if (this.isVirtualBox) {
            console.warn('VIRTUALBOX: Canvas initialization - checking WebGL support');
            this.checkWebGLSupport();
        }

        // Initialize canvas dimensions
        this.resizeCanvas();

        // Setup resize listener
        window.addEventListener('resize', () => this.resizeCanvas());

        // Run rendering diagnostics
        this.runRenderingDiagnostics();
    }

    checkWebGLSupport() {
        try {
            console.log('VIRTUALBOX: Checking WebGL support for overlay rendering');

            const canvas = document.createElement('canvas');
            const gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');

            console.log('VIRTUALBOX: WebGL context available:', !!gl);

            if (gl) {
                const debugInfo = gl.getExtension('WEBGL_debug_renderer_info');
                if (debugInfo) {
                    const renderer = gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL);
                    const vendor = gl.getParameter(debugInfo.UNMASKED_VENDOR_WEBGL);
                    console.log('VIRTUALBOX: WebGL renderer:', renderer);
                    console.log('VIRTUALBOX: WebGL vendor:', vendor);

                    // Check for software rendering indicators
                    if (renderer && (renderer.includes('Software') || renderer.includes('Mesa') || renderer.includes('LLVM'))) {
                        console.warn('VIRTUALBOX: SOFTWARE WEBGL RENDERING DETECTED - overlays may not display properly');
                        console.warn('VIRTUALBOX: This is the likely cause of invisible overlays');
                    }
                } else {
                    console.log('VIRTUALBOX: WebGL debug info not available');
                }

                // Test basic WebGL functionality
                const vertexShader = gl.createShader(gl.VERTEX_SHADER);
                const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);

                console.log('VIRTUALBOX: WebGL shader creation works:', !!(vertexShader && fragmentShader));

            } else {
                console.error('VIRTUALBOX: WebGL not available - overlays will fail to render');
                console.error('VIRTUALBOX: This is the primary cause of overlay visibility issues');
            }

        } catch (error) {
            console.error('VIRTUALBOX: WebGL check failed:', error);
        }
    }

    runRenderingDiagnostics() {
        try {
            console.log('OVERLAY: Running rendering diagnostics');

            // Check CSS rendering capabilities
            const testElement = document.createElement('div');
            testElement.style.position = 'absolute';
            testElement.style.left = '-9999px';
            testElement.style.background = 'rgba(255, 0, 0, 0.5)';
            testElement.style.width = '100px';
            testElement.style.height = '100px';
            document.body.appendChild(testElement);

            // Test CSS transparency
            const computedStyle = window.getComputedStyle(testElement);
            console.log('OVERLAY: CSS rgba() support:', computedStyle.background.includes('rgba'));

            // Test CSS transforms
            testElement.style.transform = 'translate3d(0, 0, 0)';
            const hasTransform = computedStyle.transform && computedStyle.transform !== 'none';
            console.log('OVERLAY: CSS 3D transforms support:', hasTransform);

            if (this.isVirtualBox && !hasTransform) {
                console.warn('VIRTUALBOX: CSS 3D transforms not supported - overlay positioning may fail');
            }

            // Clean up
            document.body.removeChild(testElement);

            // Check for compositor issues
            console.log('OVERLAY: Window device pixel ratio:', window.devicePixelRatio);
            console.log('OVERLAY: Screen color depth:', screen.colorDepth);
            console.log('OVERLAY: Screen pixel depth:', screen.pixelDepth);

            if (this.isVirtualBox) {
                if (window.devicePixelRatio !== 1) {
                    console.warn('VIRTUALBOX: Non-standard device pixel ratio detected - may cause rendering issues');
                }
            }

            console.log('OVERLAY: Rendering diagnostics completed');

        } catch (error) {
            console.error('OVERLAY: Rendering diagnostics failed:', error);
        }
    }

    resizeCanvas() {
        if (!this.canvas) return;
        
        // Get window dimensions
        const width = window.innerWidth;
        const height = window.innerHeight;
        
        // Update canvas dimensions
        this.canvas.width = width;
        this.canvas.height = height;
        
        // Redraw if animations are running
        if (this.animationFrame) {
            this.startCanvasAnimations();
        }
    }

    startCanvasAnimations() {
        if (!this.canvas || !this.ctx) {
            console.warn('Canvas not ready for animations');
            return;
        }
        
        const animate = () => {
            if (this.ctx && this.canvas) {
                this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
                
                // Draw animated particles or custom graphics
                this.drawParticles();
                
                this.animationFrame = requestAnimationFrame(animate);
            }
        };
        animate();
    }

    drawParticles() {
        // Example particle system - can be customized
        const time = Date.now() * 0.001;
        
        for (let i = 0; i < 5; i++) {
            const x = (Math.sin(time + i) * 100) + this.canvas.width / 2;
            const y = (Math.cos(time + i * 0.5) * 50) + this.canvas.height / 2;
            
            this.ctx.beginPath();
            this.ctx.arc(x, y, 2, 0, Math.PI * 2);
            this.ctx.fillStyle = `rgba(255, 255, 255, ${0.1 + Math.sin(time + i) * 0.1})`;
            this.ctx.fill();
        }
    }

    // Public API for Python to call
    setTitle(title) {
        // Null check for title parameter
        if (title === null || title === undefined) {
            console.warn('setTitle called with null/undefined title');
            return;
        }
        this.updateOverlay({ title });
    }

    setSubtitle(subtitle) {
        // Null check for subtitle parameter
        if (subtitle === null || subtitle === undefined) {
            console.warn('setSubtitle called with null/undefined subtitle');
            return;
        }
        this.updateOverlay({ subtitle });
    }

    setTicker(ticker) {
        // Null check for ticker parameter
        if (ticker === null || ticker === undefined) {
            console.warn('setTicker called with null/undefined ticker');
            return;
        }
        this.updateOverlay({ ticker });
    }

    showStats(show) {
        // Null check for show parameter
        if (show === null || show === undefined) {
            console.warn('showStats called with null/undefined show');
            return;
        }
        this.updateOverlay({ showStats: show });
    }

    cleanup() {
        if (this.animationFrame) {
            cancelAnimationFrame(this.animationFrame);
        }
    }
}

// Initialize overlay manager immediately and safely
let overlayManager = null;

// Function to ensure DOM is ready before any operations
function ensureOverlayReady(callback) {
    if (overlayManager && overlayManager.webChannelReady) {
        callback();
    } else {
        setTimeout(() => ensureOverlayReady(callback), 50);
    }
}

// Initialize when DOM is ready
if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', () => {
        overlayManager = new OverlayManager();
        window.overlayManager = overlayManager;
    });
} else {
    // DOM already loaded
    overlayManager = new OverlayManager();
    window.overlayManager = overlayManager;
}

// Cleanup on unload
window.addEventListener('beforeunload', () => {
    if (overlayManager) {
        overlayManager.cleanup();
    }
});

// Safe global functions that wait for overlay to be ready
window.safeUpdateOverlay = function(data) {
    // Comprehensive null/undefined check for data parameter
    if (!data) {
        console.warn('safeUpdateOverlay called with null/undefined data');
        return;
    }
    
    ensureOverlayReady(() => {
        if (overlayManager) {
            overlayManager.updateOverlay(data);
        }
    });
};

window.safeUpdateProgress = function(position, duration) {
    // Null checks for position and duration parameters
    if (position === null || position === undefined) {
        console.warn('safeUpdateProgress called with null/undefined position');
        return;
    }
    
    if (duration === null || duration === undefined) {
        console.warn('safeUpdateProgress called with null/undefined duration');
        return;
    }
    
    ensureOverlayReady(() => {
        if (overlayManager) {
            overlayManager.updateProgress(position, duration);
        }
    });
};