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

class UIController extends BaseModule {
    constructor() {
        super('ui-controller');
        
        // Declare dependencies on TTS, animation-queue, and our new UI modules
        this.dependencies = ['tts', 'animation-queue', 'ui-display-handler', 'ui-input-handler', 'ui-effects'];
        
        // 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;
        
        // Bind methods that use 'this' internally or are used as callbacks/event handlers
        this.initialize = this.initialize.bind(this); // Bind initialize as it calls dispatchEvent
        this.handleCommand = this.handleCommand.bind(this); // Bind event handler
        this.displayText = this.displayText.bind(this); // Bind if passed as callback
        this.setupBookInterface = this.setupBookInterface.bind(this);
        this.applyBookSizing = this.applyBookSizing.bind(this);
        this.setupEventListeners = this.setupEventListeners.bind(this);
        this.setupMainUI = this.setupMainUI.bind(this);
        this.initializeTextBuffer = this.initializeTextBuffer.bind(this);
        this.showUI = this.showUI.bind(this);
        this.hideUI = this.hideUI.bind(this);
        this.clearDisplay = this.clearDisplay.bind(this);
        this.sendCommand = this.sendCommand.bind(this);
        this.updateButtonStates = this.updateButtonStates.bind(this);

        // Store a bound version of dispatchEvent for use in methods
        this._dispatchModuleEvent = (name, detail) => {
            document.dispatchEvent(new CustomEvent(name, {
                detail: { moduleId: this.id, ...detail },
                bubbles: true
            }));
        };
    }

    async initialize() {
        this.reportProgress(0, 'Initializing UI Controller');
        
        try {
            this.reportProgress(20, 'Setting up book interface');
            
            // Set up book interface
            this.setupBookInterface();
            
            this.reportProgress(30, 'Setting up UI components');
            
            // Get module references
            this.displayHandler = moduleRegistry.getModule('ui-display-handler');
            this.inputHandler = moduleRegistry.getModule('ui-input-handler');
            this.effects = moduleRegistry.getModule('ui-effects');
            
            // Get additional dependencies
            this.textBuffer = moduleRegistry.getModule('text-buffer');
            this.ttsHandler = moduleRegistry.getModule('tts');
            this.socketClient = moduleRegistry.getModule('socket-client');
            this.animationQueue = moduleRegistry.getModule('animation-queue');
            
            if (!this.displayHandler || !this.inputHandler || !this.effects) {
                console.error('UI Controller: Required UI modules not found');
                return false;
            }
            
            this.reportProgress(50, 'Setting up event listeners');
            
            // Set up event listeners between components
            this.setupEventListeners();
            
            this.reportProgress(80, 'Finalizing UI initialization');
            
            // Initialize main UI container
            await this.setupMainUI();
            
            // Initialize text buffer handler
            this.initializeTextBuffer();
            
            this.isReady = true;
            this.isVisible = true;
            this.reportProgress(100, 'UI Controller ready');
            
            // Start ambient effects
            this.effects.startAmbientEffects();
            
            // Use the DOM event API directly instead of this.dispatchEvent
            this._dispatchModuleEvent('ui:ready', { controller: this });
            
            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
        window.addEventListener('resize', () => this.applyBookSizing());
    }
    
    applyBookSizing() {
        // Apply book sizing based on viewport dimensions
        const viewportWidth = window.innerWidth;
        const viewportHeight = window.innerHeight;
        const aspectRatio = viewportWidth / viewportHeight;
        
        document.documentElement.style.setProperty('--viewport-aspect-ratio', aspectRatio);
        
        const maxBookHeight = viewportHeight * 0.9;
        document.documentElement.style.setProperty('--book-height', `${maxBookHeight}px`);
        
        const bookWidth = maxBookHeight * Math.min(aspectRatio, 1.613);
        document.documentElement.style.setProperty('--book-width', `${bookWidth}px`);
    }

    setupEventListeners() {
        // Listen for command events from input handler - use arrow function to preserve context
        document.addEventListener('ui:command', (event) => {
            this.handleCommand(event.detail);
        });
        
        // Listen for text display events - use arrow function to preserve context
        document.addEventListener('ui:text:complete', () => {
            // Use the DOM event API directly
            this._dispatchModuleEvent('ui:ready:for:next', {});
        });
        
        // Listen for socket connection events
        document.addEventListener('socket:connected', () => {
            console.log('UI Controller: Socket connected');
        });
        
        document.addEventListener('socket:disconnected', () => {
            console.log('UI Controller: Socket disconnected');
        });
        
        // Handle speed reset
        const speedReset = document.getElementById('speed_reset');
        if (speedReset) {
            speedReset.addEventListener('click', (e) => {
                e.preventDefault();
                const speedSlider = document.getElementById('speed');
                if (speedSlider) {
                    speedSlider.value = 50;
                    if (this.animationQueue) {
                        this.animationQueue.setSpeed(1.0);
                    }
                }
            });
        }
        
        // Handle speed slider change for animation speed
        const speedSlider = document.getElementById('speed');
        if (speedSlider) {
            speedSlider.addEventListener('input', (e) => {
                if (this.animationQueue) {
                    // Convert slider value (0-100) to animation speed
                    // Using formula from Documentation.md: lower values = slower speed
                    const value = parseInt(e.target.value);
                    const speed = Math.pow(100.0 - value, 3) / 10000 * 10 + 0.01;
                    this.animationQueue.setSpeed(speed);
                    console.log(`UI Controller: Animation speed set to ${speed.toFixed(3)}`);
                    
                    // Save to persistence manager if available
                    if (window.PersistenceManager) {
                        window.PersistenceManager.updatePreference('animation', 'speed', value);
                    }
                }
            });
            
            // Set initial speed from persistence manager if available
            if (window.PersistenceManager) {
                const savedSpeed = window.PersistenceManager.getPreference('animation', 'speed', 50);
                speedSlider.value = savedSpeed;
                // Apply initial speed
                if (this.animationQueue) {
                    const speed = Math.pow(100.0 - savedSpeed, 3) / 10000 * 10 + 0.01;
                    this.animationQueue.setSpeed(speed);
                }
            }
        }
        
        // Handle speech toggle with proper state management
        const speechToggle = document.getElementById('speech');
        if (speechToggle && this.ttsHandler) {
            // Remove disabled attribute to make it clickable
            speechToggle.removeAttribute('disabled');
            
            speechToggle.addEventListener('click', (e) => {
                e.preventDefault();
                console.log('Speech toggle clicked');
                
                // Toggle TTS state
                if (this.ttsHandler && typeof this.ttsHandler.toggle === 'function') {
                    this.ttsEnabled = this.ttsHandler.toggle();
                    
                    // Update button text
                    speechToggle.textContent = this.ttsEnabled ? 'mute' : 'speech';
                    
                    // Save preference if persistence manager is available
                    const persistenceManager = moduleRegistry.getModule('persistence-manager');
                    if (persistenceManager) {
                        persistenceManager.updatePreference('tts', 'enabled', this.ttsEnabled);
                    }
                    
                    console.log(`UI Controller: TTS ${this.ttsEnabled ? 'enabled' : 'disabled'}`);
                } else {
                    console.warn('TTS Handler does not have toggle method');
                }
            });
        }
        
        // Add options button to controls section
        const controlsSection = document.getElementById('controls');
        if (controlsSection) {
            // Check if options button already exists
            if (!document.getElementById('options-button')) {
                const optionsButton = document.createElement('a');
                optionsButton.id = 'options-button';
                optionsButton.href = '#';
                optionsButton.textContent = 'options';
                optionsButton.title = 'Show game options';
                
                // Add event listener
                optionsButton.addEventListener('click', (e) => {
                    e.preventDefault();
                    const optionsUI = moduleRegistry.getModule('options-ui');
                    if (optionsUI && optionsUI.toggle) {
                        optionsUI.toggle();
                    }
                });
                
                // Add to controls
                controlsSection.appendChild(document.createTextNode(' | '));
                controlsSection.appendChild(optionsButton);
            }
        }
        
        // Enable all controls buttons
        const controlButtons = document.querySelectorAll('#controls a');
        controlButtons.forEach(button => {
            button.removeAttribute('disabled');
        });
        
        // Book click for fast-forwarding - make sure it triggers the animation queue
        if (this.bookElement) {
            this.bookElement.addEventListener('click', (event) => {
                // Only if not clicking on a link or control
                if (event.target.tagName !== 'A' && 
                    !event.target.closest('#controls') && 
                    !event.target.closest('#command_input')) {
                    if (this.animationQueue) {
                        console.log('UI Controller: Fast-forwarding animations');
                        this.animationQueue.fastForward();
                    }
                }
            });
        }
        
        // Space key for fast-forwarding
        document.addEventListener('keydown', (e) => {
            if (e.key === ' ' && 
                document.activeElement.tagName !== 'TEXTAREA' && 
                document.activeElement.tagName !== 'INPUT') {
                if (this.animationQueue) {
                    console.log('UI Controller: Fast-forwarding animations (space key)');
                    this.animationQueue.fastForward();
                    e.preventDefault(); // Prevent page scrolling
                }
            }
        });
    }
    
    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');
        }
    }
    
    initializeTextBuffer() {
        // Initialize text buffer handling
        if (this.textBuffer) {
            this.textBuffer.setOnSentenceReady((text, callback) => {
                console.log('UI Controller: Displaying sentence');
                this.displayText(text).then(callback);
            });
        }
    }
    
    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':
                if (this.animationQueue) {
                    this.animationQueue.fastForward();
                }
                break;
            case 'input':
                if (this.socketClient) {
                    this.socketClient.sendCommand(command.text);
                }
                break;
            case 'menu':
                // Toggle options menu
                const optionsUI = moduleRegistry.getModule('options-ui');
                if (optionsUI) {
                    optionsUI.toggle();
                }
                break;
            default:
                // Handle general UI commands or pass to game logic
                this._dispatchModuleEvent('ui:command', command);
        }
    }
    
    /**
     * Update UI button states based on game state
     * @param {Object} state - Game state information
     */
    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');
        
        // Update save button state
        if (saveButton) {
            if (canSave) {
                saveButton.removeAttribute('disabled');
            } else {
                saveButton.setAttribute('disabled', 'disabled');
            }
        }
        
        // Update load button state
        if (loadButton) {
            if (canLoad) {
                loadButton.removeAttribute('disabled');
            } else {
                loadButton.setAttribute('disabled', 'disabled');
            }
        }
        
        // Update restart button state
        if (restartButton) {
            if (canRestart) {
                restartButton.removeAttribute('disabled');
            } else {
                restartButton.setAttribute('disabled', 'disabled');
            }
        }
    }
    
    // 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();
        }
    }
    
    displayText(text, options = {}) {
        return this.displayHandler.displayText(text, options);
    }
    
    clearDisplay() {
        this.displayHandler.clear();
    }
    
    sendCommand(command) {
        if (this.socketClient) {
            return this.socketClient.sendCommand(command);
        }
        return false;
    }
}

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

// Register with the module registry
moduleRegistry.register(uiController);

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

// Keep a reference in window for loader system
window.UIController = uiController;
