import { BaseModule } from './base-module.js';
import { ModuleEvent } from './base-module.js';

class UIControllerModule extends BaseModule {
    constructor() {
        super('ui-controller', 'UI Controller');
        
        // Remove 'tts' from direct dependencies to break circular dependency
        // UI Controller will access TTS through the Game Loop instead
        this.dependencies = ['animation-queue', 'ui-display-handler', 'ui-input-handler', 'ui-effects', 'text-buffer', 'socket-client', 'sentence-queue', 'playback-coordinator', 'persistence-manager'];
        
        // References to sub-modules
        this.displayHandler = null;
        this.inputHandler = null;
        this.effects = null;
        
        // UI state
        this.isReady = false;
        this.isVisible = false;
        
        // Book interface elements
        this.bookElement = null;
        this.leftPage = null;
        this.rightPage = null;
        this.storyElement = null;
        
        // Additional module references
        this.textBuffer = null;
        this.ttsHandler = null;
        this.socketClient = null;
        this.animationQueue = null;
        
        // Add TTS toggle state
        this.ttsEnabled = false;
        this.ttsAvailable = true; // Add TTS availability state
        
        // Bind methods using the parent class bindMethods utility
        this.bindMethods([
            'initialize',
            'handleCommand',
            'setupBookInterface',
            'applyBookSizing',
            'setupEventListeners',
            'setupMainUI',
            'bindTopControls',
            'syncTopControls',
            'getStoredTtsPreference',
            'setStoredTtsPreference',
            'getStoredAppPreference',
            'setStoredAppPreference',
            'sliderValueFromSpeed',
            'speedFromSliderValue',
            'initializeTextBuffer',
            'showUI',
            'hideUI',
            'clearDisplay',
            'sendCommand',
            'updateButtonStates'
        ]);
    }

    async initialize() {
        try {
            this.reportProgress(0, 'Initializing UI Controller');
            
            this.reportProgress(20, 'Setting up book interface');
            
            // Set up book interface
            this.setupBookInterface();
            
            this.reportProgress(30, 'Getting module dependencies');
            
            // Get module references using parent's getModule method
            this.displayHandler = this.getModule('ui-display-handler');
            this.inputHandler = this.getModule('ui-input-handler');
            this.effects = this.getModule('ui-effects');
            this.textBuffer = this.getModule('text-buffer');
            this.socketClient = this.getModule('socket-client');
            this.animationQueue = this.getModule('animation-queue');
            
            // Check for required UI modules
            if (!this.displayHandler) {
                console.error('UI Controller: Display handler module not found');
                return false;
            }
            
            if (!this.inputHandler) {
                console.error('UI Controller: Input handler module not found');
                return false;
            }
            
            if (!this.effects) {
                console.error('UI Controller: UI effects module not found');
                return false;
            }
            
            // Check for other required modules
            if (!this.textBuffer) {
                console.error('UI Controller: Text buffer module not found');
                return false;
            }
            
            if (!this.socketClient) {
                console.error('UI Controller: Socket client module not found');
                return false;
            }
            
            if (!this.animationQueue) {
                console.error('UI Controller: Animation queue module not found');
                return false;
            }
            
            this.reportProgress(50, 'Setting up main UI');
            
            // Initialize main UI container
            await this.setupMainUI();

            this.reportProgress(70, 'Setting up event listeners');
            
            // Set up event listeners after the display handler has created controls
            this.setupEventListeners();
            this.bindTopControls();
            this.syncTopControls();
            requestAnimationFrame(() => {
                this.bindTopControls();
                this.syncTopControls();
            });
            setTimeout(() => {
                this.bindTopControls();
                this.syncTopControls();
            }, 250);
            
            this.reportProgress(80, 'Initializing text buffer');
            
            // Initialize text buffer handler
            this.initializeTextBuffer();
            
            this.reportProgress(100, 'UI Controller ready');
            
            this.isReady = true;
            this.isVisible = true;
            this.dispatchEvent(new ModuleEvent('ui:ready', { controller: this }));
            
            // Start ambient effects
            this.effects.startAmbientEffects();
            
            return true;
        } catch (error) {
            console.error('Error initializing UI Controller:', error);
            this.changeState('ERROR');
            return false;
        }
    }

    setupBookInterface() {
        // Create or get the book interface elements
        this.bookElement = document.getElementById('book');
        this.leftPage = document.getElementById('page_left');
        this.rightPage = document.getElementById('page_right');
        this.storyElement = document.getElementById('story');
        
        // Apply book sizing based on viewport
        this.applyBookSizing();
        
        // Set up window resize handler
        const handleViewportResize = () => this.applyBookSizing();
        window.addEventListener('resize', handleViewportResize);
        if (window.visualViewport) {
            window.visualViewport.addEventListener('resize', handleViewportResize);
        }
        if (window.ResizeObserver && document.body) {
            this.bodyResizeObserver = new ResizeObserver(handleViewportResize);
            this.bodyResizeObserver.observe(document.body);
        }
    }
    
    applyBookSizing() {
        const viewportWidth = window.innerWidth;
        const viewportHeight = window.innerHeight;
        const viewportAspectRatio = viewportWidth / viewportHeight;
        const bookWidth = 1421;
        const bookHeight = 799;
        const bookScale = Math.min(viewportWidth / bookWidth, viewportHeight / bookHeight);
        
        document.documentElement.style.setProperty('--book-width', `${bookWidth}px`);
        document.documentElement.style.setProperty('--book-height', `${bookHeight}px`);
        document.documentElement.style.setProperty('--book-scale', bookScale);
        document.documentElement.style.setProperty('--viewport-aspect-ratio', viewportAspectRatio);
        document.documentElement.style.setProperty(
            '--viewport-dimension',
            viewportWidth / viewportHeight > bookWidth / bookHeight ? 'vw' : 'vh'
        );

        document.dispatchEvent(new CustomEvent('book:scaled', {
            detail: {
                bookWidth,
                bookHeight,
                bookScale,
                displayWidth: bookWidth * bookScale,
                displayHeight: bookHeight * bookScale,
                viewportWidth,
                viewportHeight
            }
        }));
    }

    setupEventListeners() {
        // Set up event listeners for menu buttons
        const saveButton = document.getElementById('save');
        const loadButton = document.getElementById('reload');
        const restartButton = document.getElementById('rewind');
        const optionsButton = document.getElementById('options');
        
        // Get persistence manager module
        const persistenceManager = this.getModule('persistence-manager');
        const ttsFactory = this.getModule('tts-factory');
        
        // Set up save button
        if (saveButton) {
            saveButton.addEventListener('click', (event) => {
                event.preventDefault();
                if (saveButton.getAttribute('disabled') === 'disabled') return;
                document.dispatchEvent(new CustomEvent('ui:game:save'));
            });
        }
        
        // Set up load button
        if (loadButton) {
            loadButton.addEventListener('click', (event) => {
                event.preventDefault();
                if (loadButton.getAttribute('disabled') === 'disabled') return;
                document.dispatchEvent(new CustomEvent('ui:game:load'));
            });
        }
        
        // Set up restart button
        if (restartButton) {
            restartButton.addEventListener('click', (event) => {
                event.preventDefault();
                event.__newGameHandled = true;
                document.dispatchEvent(new CustomEvent('ui:game:restart'));
            });
        }

        this.addEventListener(document, 'click', (event) => {
            if (event.target && event.target.closest && event.target.closest('#rewind')) {
                event.preventDefault();
                if (event.__newGameHandled) return;
                document.dispatchEvent(new CustomEvent('ui:game:restart'));
            }
        });
        
        // Set up options button
        if (optionsButton) {
            optionsButton.addEventListener('click', () => {
                document.dispatchEvent(new CustomEvent('ui:options:toggle'));
            });
        }

        this.addEventListener(document, 'ui:command', (event) => {
            if (!event.detail || event.detail.moduleId === this.id) return;
            this.handleCommand(event.detail);
        });

        this.addEventListener(document, 'click', (event) => {
            if (event.target && event.target.closest && event.target.closest('#options-modal, #controls, #player_input, #command_input, #story_scrollbar')) {
                return;
            }

            const playbackCoordinator = this.getModule('playback-coordinator');
            const hasSkippablePause = document.documentElement.dataset.skippablePause === 'true';
            if ((playbackCoordinator && playbackCoordinator.isPlaying) || hasSkippablePause) {
                this.handleCommand({ type: 'continue', source: 'book-click' });
            }

            if (this.inputHandler && typeof this.inputHandler.focusInput === 'function') {
                this.inputHandler.focusInput();
            }
        });
        
        // Listen for book events
        document.addEventListener('book:ready', () => {
            this.bindTopControls();
            this.syncTopControls();
            this.updateButtonStates({
                canSave: true,
                canLoad: true,
                canRestart: true
            });
        });
        
        // Listen for restart events
        document.addEventListener('story:restart', () => {
            this.updateButtonStates({
                canSave: true,
                canLoad: false,
                canRestart: false
            });
        });
        
        // Listen for save events
        document.addEventListener('story:save', () => {
            this.updateButtonStates({
                canSave: true,
                canLoad: true,
                canRestart: true
            });
        });
        
        // Listen for TTS availability changes
        document.addEventListener('tts:availability', (event) => {
            if (event.detail && typeof event.detail.available === 'boolean') {
                this.ttsAvailable = event.detail.available;
                this.updateButtonStates();
            }
        });
        
        // Listen for TTS state changes (from options UI or TTS player)
        document.addEventListener('tts:stateChange', (event) => {
            if (event.detail && typeof event.detail.enabled === 'boolean') {
                this.ttsEnabled = event.detail.enabled;
                this.updateButtonStates();
                
                // Ensure persistence is updated
                const currentPersistenceManager = this.getModule('persistence-manager');
                if (currentPersistenceManager) {
                    currentPersistenceManager.updatePreference('tts', 'enabled', this.ttsEnabled);
                }
            }
        });
        
        // Listen for TTS engine changes
        document.addEventListener('tts:engine:change', (event) => {
            // Update button states since TTS engine changed
            this.updateButtonStates();
        });
        
        // Listen for TTS toggle events from other components
        document.addEventListener('tts:enabled:change', (event) => {
            if (event.detail && typeof event.detail.enabled === 'boolean') {
                this.ttsEnabled = event.detail.enabled;
                this.updateButtonStates();
                
                // Ensure persistence is updated
                const currentPersistenceManager = this.getModule('persistence-manager');
                if (currentPersistenceManager) {
                    currentPersistenceManager.updatePreference('tts', 'enabled', this.ttsEnabled);
                }
            }
        });

        document.addEventListener('preference-updated', (event) => {
            const { category, key, value } = event.detail || {};
            if (category !== 'tts') {
                if (category === 'app' && key === 'autoplay') {
                    this.syncTopControls();
                }
                return;
            }

            if (key === 'enabled') {
                this.ttsEnabled = value === true;
                this.syncTopControls();
            } else if (key === 'speed') {
                this.syncTopControls();
            }
        });
        
        // Listen for speed change events from other components
        document.addEventListener('tts:speed:change', (event) => {
            if (event.detail && typeof event.detail.speed === 'number') {
                // Update the main UI speed slider
                const speedSlider = document.getElementById('speed');
                if (speedSlider) {
                    speedSlider.value = this.sliderValueFromSpeed(event.detail.speed);
                }
                
                // Save to persistence manager
                const currentPersistenceManager = this.getModule('persistence-manager');
                if (currentPersistenceManager) {
                    currentPersistenceManager.updatePreference('tts', 'speed', event.detail.speed);
                }
            }
        });
    }

    sliderValueFromSpeed(speed) {
        const value = Number.isFinite(Number(speed)) ? Number(speed) : 1;
        return Math.round((Math.max(0.5, Math.min(2.0, value)) * 50) + 50);
    }

    speedFromSliderValue(value) {
        const sliderValue = Number.isFinite(Number(value)) ? Number(value) : 50;
        return Math.max(0.5, Math.min(2.0, (sliderValue - 50) / 50));
    }

    bindTopControls() {
        const speechToggle = document.getElementById('speech');
        const autoplayToggle = document.getElementById('autoplay');
        const speedSlider = document.getElementById('speed');
        const speedReset = document.getElementById('speed_reset');

        if (speechToggle && speechToggle.dataset.uiControllerBound !== 'true') {
            speechToggle.dataset.uiControllerBound = 'true';
            speechToggle.removeAttribute('disabled');
            speechToggle.addEventListener('click', async (event) => {
                event.preventDefault();
                event.stopPropagation();

                const persistenceManager = this.getModule('persistence-manager');
                const ttsFactory = this.getModule('tts-factory');
                const currentEnabled = this.getStoredTtsPreference('enabled', this.ttsEnabled);
                const nextEnabled = !currentEnabled;
                this.ttsEnabled = nextEnabled;
                console.log(`UIController: Top speech toggle set to ${nextEnabled ? 'enabled' : 'disabled'}`);

                this.setStoredTtsPreference('enabled', nextEnabled);

                if (ttsFactory) {
                    if (nextEnabled) {
                        const preferredHandler = persistenceManager?.getPreference('tts', 'preferred_handler', 'none') || 'none';
                        if (preferredHandler !== 'none') {
                            await ttsFactory.setActiveHandler(preferredHandler);
                        }
                    } else {
                        await ttsFactory.disableAfterCurrentPlayback();
                    }
                }

                this.syncTopControls();
                document.dispatchEvent(new CustomEvent('tts:enabled:change', {
                    detail: { enabled: nextEnabled, source: 'topbar' }
                }));
            });
        }

        if (autoplayToggle && autoplayToggle.dataset.uiControllerBound !== 'true') {
            autoplayToggle.dataset.uiControllerBound = 'true';
            autoplayToggle.removeAttribute('disabled');
            autoplayToggle.addEventListener('click', (event) => {
                event.preventDefault();
                event.stopPropagation();
                const nextAutoplay = !this.getStoredAppPreference('autoplay', true);
                this.setStoredAppPreference('autoplay', nextAutoplay);
                console.log(`UIController: Autoplay set to ${nextAutoplay ? 'enabled' : 'disabled'}`);
                this.syncTopControls();
                document.dispatchEvent(new CustomEvent('app:autoplay:change', {
                    detail: { enabled: nextAutoplay, source: 'topbar' }
                }));
            });
        }

        if (speedSlider && speedSlider.dataset.uiControllerBound !== 'true') {
            speedSlider.dataset.uiControllerBound = 'true';
            speedSlider.min = speedSlider.min || '50';
            speedSlider.max = speedSlider.max || '150';
            speedSlider.addEventListener('input', (event) => {
                const persistenceManager = this.getModule('persistence-manager');
                const speed = this.speedFromSliderValue(event.target.value);

                document.dispatchEvent(new CustomEvent('animation:speed:change', {
                    detail: { speed: 1 }
                }));

                document.dispatchEvent(new CustomEvent('tts:speed:change', {
                    detail: { speed }
                }));

                this.setStoredTtsPreference('speed', speed);
            });
        }

        if (speedReset && speedReset.dataset.uiControllerBound !== 'true') {
            speedReset.dataset.uiControllerBound = 'true';
            speedReset.addEventListener('click', () => {
                const slider = document.getElementById('speed');
                if (slider) {
                    slider.value = this.sliderValueFromSpeed(1);
                    slider.dispatchEvent(new Event('input'));
                }
            });
        }
    }

    syncTopControls() {
        this.bindTopControls();

        this.ttsEnabled = this.getStoredTtsPreference('enabled', this.ttsEnabled) === true;

        const speedSlider = document.getElementById('speed');
        if (speedSlider) {
            const speed = this.getStoredTtsPreference('speed', 1);
            const value = String(this.sliderValueFromSpeed(speed));
            if (speedSlider.value !== value) {
                speedSlider.value = value;
            }
        }

        this.updateButtonStates();
    }

    getStoredTtsPreference(key, defaultValue) {
        const persistenceManager = this.getModule('persistence-manager');
        if (persistenceManager && typeof persistenceManager.getPreference === 'function') {
            const value = persistenceManager.getPreference('tts', key, undefined);
            if (typeof value !== 'undefined' && value !== null) {
                return value;
            }
        }

        try {
            const raw = localStorage.getItem('ai-interactive-fiction-preferences');
            if (raw) {
                const prefs = JSON.parse(raw);
                if (prefs && prefs.tts && Object.prototype.hasOwnProperty.call(prefs.tts, key)) {
                    return prefs.tts[key];
                }
            }
        } catch (error) {
            console.warn('UIController: Failed to read TTS preference fallback:', error);
        }

        return defaultValue;
    }

    setStoredTtsPreference(key, value) {
        const persistenceManager = this.getModule('persistence-manager');
        if (persistenceManager && typeof persistenceManager.updatePreference === 'function') {
            persistenceManager.updatePreference('tts', key, value);
        }

        try {
            const storageKey = 'ai-interactive-fiction-preferences';
            const raw = localStorage.getItem(storageKey);
            const prefs = raw ? JSON.parse(raw) : {};
            prefs.tts = prefs.tts || {};
            prefs.tts[key] = value;
            localStorage.setItem(storageKey, JSON.stringify(prefs));
        } catch (error) {
            console.warn('UIController: Failed to write TTS preference fallback:', error);
        }
    }

    getStoredAppPreference(key, defaultValue) {
        const persistenceManager = this.getModule('persistence-manager');
        if (persistenceManager && typeof persistenceManager.getPreference === 'function') {
            const value = persistenceManager.getPreference('app', key, undefined);
            if (typeof value !== 'undefined' && value !== null) {
                return value;
            }
        }

        try {
            const raw = localStorage.getItem('ai-interactive-fiction-preferences');
            if (raw) {
                const prefs = JSON.parse(raw);
                if (prefs && prefs.app && Object.prototype.hasOwnProperty.call(prefs.app, key)) {
                    return prefs.app[key];
                }
            }
        } catch (error) {
            console.warn('UIController: Failed to read app preference fallback:', error);
        }

        return defaultValue;
    }

    setStoredAppPreference(key, value) {
        const persistenceManager = this.getModule('persistence-manager');
        if (persistenceManager && typeof persistenceManager.updatePreference === 'function') {
            persistenceManager.updatePreference('app', key, value);
        }

        try {
            const storageKey = 'ai-interactive-fiction-preferences';
            const raw = localStorage.getItem(storageKey);
            const prefs = raw ? JSON.parse(raw) : {};
            prefs.app = prefs.app || {};
            prefs.app[key] = value;
            localStorage.setItem(storageKey, JSON.stringify(prefs));
        } catch (error) {
            console.warn('UIController: Failed to write app preference fallback:', error);
        }
    }
    
    async setupMainUI() {
        // Ensure all UI components exist
        if (!this.bookElement || !this.leftPage || !this.rightPage || !this.storyElement) {
            console.log('UI Controller: Creating missing UI elements');
            this.displayHandler.setupBookStructure();
            
            // Re-get elements
            this.bookElement = document.getElementById('book');
            this.leftPage = document.getElementById('page_left');
            this.rightPage = document.getElementById('page_right');
            this.storyElement = document.getElementById('story');
        }

        if (this.inputHandler && typeof this.inputHandler.focusInput === 'function') {
            requestAnimationFrame(() => this.inputHandler.focusInput());
        }
    }
    
    initializeTextBuffer() {
        // Connect SentenceQueue to UIDisplayHandler
        const sentenceQueue = this.getModule('sentence-queue');
        const displayHandler = this.getModule('ui-display-handler');

        if (!sentenceQueue || !displayHandler) {
            console.error('UIController: Required modules not found (sentence-queue or ui-display-handler)');
            return;
        }

        console.log('UIController: Setting up SentenceQueue → UIDisplayHandler pipeline');

        // Set up callback for when sentences are ready to display
        sentenceQueue.setOnSentenceReady(async (sentence, callback) => {
            try {
                console.log(`UIController: Rendering sentence ${sentence.id}`);
                await displayHandler.renderSentence(sentence);
                console.log(`UIController: Sentence ${sentence.id} rendered successfully`);

                // Signal completion to process next sentence
                if (typeof callback === 'function') {
                    callback();
                }
            } catch (error) {
                console.error('UIController: Error rendering sentence:', error);
                // Still proceed to prevent blocking
                if (typeof callback === 'function') {
                    callback();
                }
            }
        });

        console.log('UIController: SentenceQueue pipeline configured');
    }
    
    handleCommand(command) {
        // Route commands to appropriate handlers
        switch (command.type) {
            case 'display':
                this.displayHandler.processCommand(command);
                break;
            case 'effect':
                this.effects.processCommand(command);
                break;
            case 'continue':
                {
                    document.dispatchEvent(new CustomEvent('ui:command', {
                        detail: { moduleId: this.id, type: 'continue', source: command.source || 'ui-controller-forward' }
                    }));
                    const playbackCoordinator = this.getModule('playback-coordinator');
                    if (playbackCoordinator && playbackCoordinator.isPlaying) {
                        playbackCoordinator.fastForward();
                    } else if (this.animationQueue) {
                        this.animationQueue.fastForward();
                    }
                }
                break;
            case 'input':
                if (this.socketClient) {
                    console.log(`UI Controller: Sending command to socket: "${command.text}"`);
                    const success = this.socketClient.sendCommand(command.text);
                    
                    if (success) {
                        console.log('UI Controller: Command sent successfully');
                    } else {
                        console.error('UI Controller: Failed to send command to socket');
                        document.dispatchEvent(new CustomEvent('story:process-state', {
                            detail: { state: 'ready', reason: 'command-send-failed' }
                        }));
                    }
                } else {
                    console.error('UI Controller: Socket client not available for sending commands');
                }
                break;
            case 'menu':
                // Toggle options menu
                const optionsUI = this.getModule('options-ui');
                if (optionsUI) {
                    optionsUI.toggle();
                }
                break;
            default:
                // Handle general UI commands or pass to game logic
                this.dispatchEvent(new ModuleEvent('ui:command', command));
        }
    }
    
    /**
     * Update UI button states based on game state
     */
    updateButtonStates(state = {}) {
        const { canSave, canLoad, canRestart } = state;
        
        // Get button elements
        const saveButton = document.getElementById('save');
        const loadButton = document.getElementById('reload');
        const restartButton = document.getElementById('rewind');
        const speechToggle = document.getElementById('speech');
        const autoplayToggle = document.getElementById('autoplay');
        
        // Update save button state
        if (saveButton && typeof canSave === 'boolean') {
            if (canSave) {
                saveButton.removeAttribute('disabled');
            } else {
                saveButton.setAttribute('disabled', 'disabled');
            }
        }
        
        // Update load button state
        if (loadButton && typeof canLoad === 'boolean') {
            if (canLoad) {
                loadButton.removeAttribute('disabled');
            } else {
                loadButton.setAttribute('disabled', 'disabled');
            }
        }
        
        // Update restart button state
        if (restartButton && typeof canRestart === 'boolean') {
            if (canRestart) {
                restartButton.removeAttribute('disabled');
            } else {
                restartButton.setAttribute('disabled', 'disabled');
            }
        }

        if (typeof state.gameStarted === 'boolean') {
            document.body.dataset.gameRunning = state.gameStarted ? 'true' : 'false';
        }
        
        // Update speech toggle button state
        if (speechToggle) {
            // Update the button appearance based on TTS state using existing styles
            speechToggle.removeAttribute('disabled');
            if (this.ttsEnabled) {
                speechToggle.style.fontWeight = 'bold';
                speechToggle.style.color = '#000';
                speechToggle.title = this.ttsAvailable ? 'Disable speech' : 'Speech enabled, selected provider is not ready';
            } else {
                speechToggle.style.fontWeight = 'normal';
                speechToggle.style.color = '#999';
                speechToggle.title = 'Enable speech';
            }
        }

        if (autoplayToggle) {
            const autoplay = this.getStoredAppPreference('autoplay', true) !== false;
            autoplayToggle.removeAttribute('disabled');
            autoplayToggle.style.fontWeight = autoplay ? 'bold' : 'normal';
            autoplayToggle.style.color = autoplay ? '#000' : '#999';
        }
    }
    
    // Public API methods
    
    showUI() {
        if (!this.isVisible) {
            this.isVisible = true;
            this.displayHandler.show();
            this.effects.startAmbientEffects();
        }
    }
    
    hideUI() {
        if (this.isVisible) {
            this.isVisible = false;
            this.displayHandler.hide();
            this.effects.stopAmbientEffects();
        }
    }
    
    clearDisplay() {
        this.displayHandler.clear();
    }
    
    sendCommand(command) {
        if (this.socketClient) {
            return this.socketClient.sendCommand(command);
        }
        return false;
    }
}

// Create the singleton instance
const uiController = new UIControllerModule();

// Export the module
export { uiController as UIController };

