/**
 * TTS Player Module for AI Interactive Fiction
 * Handles Text-to-Speech functionality with resource-aware loading and progress reporting
 */
import { BaseModule, ModuleEvent } from './base-module.js';
import { moduleRegistry } from './module-registry.js';

class TTSPlayerModule extends BaseModule {
    constructor() {
        super('tts', 'Text-to-Speech');
        this.ttsFactory = null;
        this.isInitialized = false;
        this.kokoroLoadingPromise = null;
        this.kokoroLoadingStarted = false;
    }
    
    /**
     * Load module dependencies
     * @returns {Promise} - Resolves when dependencies are loaded
     */
    async loadDependencies() {
        try {
            // Import the TTS Factory module
            const { ttsFactory } = await import('./tts-factory.js');
            this.ttsFactory = ttsFactory;
            this.reportProgress(20, "TTS Factory loaded");
            
            // Set up event listeners
            window.addEventListener('tts-ready', this.handleTTSReadyEvent.bind(this));
            
            // Create a Promise that resolves when Kokoro is loaded
            this.kokoroLoadingPromise = new Promise(resolve => {
                // Listen for when Kokoro starts loading
                window.addEventListener('kokoro-loading-started', () => {
                    this.kokoroLoadingStarted = true;
                    this.reportProgress(50, "Loading Kokoro TTS");
                });
                
                // Listen for when Kokoro completes loading
                window.addEventListener('kokoro-loading-complete', (event) => {
                    // Check if loading was successful from the event details
                    if (event.detail && event.detail.success === false) {
                        this.reportProgress(95, "Kokoro TTS failed to load - using fallback");
                        console.warn("Kokoro failed to load:", event.detail?.error || "unknown error");
                    } else {
                        this.reportProgress(95, "Kokoro TTS loaded");
                    }
                    resolve();
                });
            });
            
            return true;
        } catch (error) {
            console.error("Error loading TTS dependencies:", error);
            return false;
        }
    }
    
    /**
     * Initialize the module
     * @returns {Promise<boolean>} - Resolves with success status
     */
    async initialize() {
        try {
            // Initialize TTS Factory
            await this.ttsFactory.constructor.initializeInterface((percent, message) => {
                // Scale to 20-90% of our progress range
                const scaledPercent = 20 + (percent * 0.7);
                this.reportProgress(scaledPercent, message);
            });
            
            // IMPORTANT: Always wait for Kokoro's loading promise to resolve
            this.reportProgress(90, "Waiting for Kokoro TTS to complete loading");
            
            // Wait for the Kokoro loading promise to complete with a timeout
            try {
                // Add a timeout to prevent waiting forever
                const timeoutPromise = new Promise(resolve => setTimeout(() => {
                    console.log("TTS Player: Kokoro loading timed out, continuing without Kokoro");
                    resolve(false);
                }, 10000)); // 10 second timeout
                
                // Race between normal completion and timeout
                await Promise.race([this.kokoroLoadingPromise, timeoutPromise]);
                
                this.reportProgress(95, "Kokoro TTS loading completed or timed out");
            } catch (err) {
                console.warn("TTS Player: Error waiting for Kokoro:", err);
                this.reportProgress(95, "Error waiting for Kokoro, continuing anyway");
            }
            
            this.isInitialized = true;
            
            // Final status check
            const ttsInfo = this.ttsFactory.getActiveTTSInfo();
            if (ttsInfo.available) {
                this.reportProgress(100, `TTS Player initialized using ${ttsInfo.name}`);
                return true;
            } else {
                this.reportProgress(100, "TTS initialization complete but no voices available");
                return true; // Still consider this a success, just with no voices
            }
        } catch (error) {
            console.error("Error initializing TTS Player:", error);
            this.reportProgress(100, "TTS initialization failed, continuing without TTS");
            this.isInitialized = true; // Mark as initialized anyway to not block other modules
            return true; // Return true to not block the application
        }
    }
    
    /**
     * Handle TTS ready event from the factory
     * @param {CustomEvent} event - The TTS ready event
     */
    handleTTSReadyEvent(event) {
        const { available, type } = event.detail;
        
        if (available && type) {
            this.reportProgress(95, `TTS system ready: ${type}`);
        } else {
            this.reportProgress(95, "No TTS system available");
        }
    }
    
    // Public API methods
    
    /**
     * Get information about the active TTS system
     * @returns {Object} - TTS system info
     */
    getTTSInfo() {
        if (!this.ttsFactory) return { available: false, type: 'none', name: 'None' };
        return this.ttsFactory.getActiveTTSInfo();
    }
    
    /**
     * Toggle TTS functionality on/off
     * @returns {boolean} - New TTS enabled state
     */
    toggle() {
        if (!this.ttsFactory) return false;
        return this.ttsFactory.toggle();
    }
    
    /**
     * Speak text using the active TTS system
     * @param {string} text - Text to speak
     * @param {Function} callback - Called when speech completes
     */
    speak(text, callback) {
        if (!this.ttsFactory) {
            console.warn("TTS Factory not available for speak");
            if (callback) callback("TTS not available");
            return;
        }
        
        console.log(`TTS Player speaking: "${text}"`);
        this.ttsFactory.speak(text, (result) => {
            console.log("TTS Player speak complete", result);
            if (callback) callback(result);
        });
    }
    
    /**
     * Stop any ongoing speech
     */
    stop() {
        if (this.ttsFactory) {
            this.ttsFactory.stop();
        }
    }
    
    /**
     * Set voice options for the active TTS system
     * @param {Object} options - Voice options
     */
    setVoiceOptions(options) {
        if (this.ttsFactory) {
            this.ttsFactory.setVoiceOptions(options);
        }
    }
    
    /**
     * Set speech rate/speed
     * @param {number} speed - Speech rate (0.5-2.0)
     */
    setSpeed(speed) {
        this.setVoiceOptions({ rate: speed });
    }
    
    /**
     * Set the volume for speech
     * @param {number} volume - Volume level (0.0-1.0)
     */
    setVolume(volume) {
        this.setVoiceOptions({ volume: volume });
    }
    
    /**
     * Set the voice for speech
     * @param {string} voice - Voice identifier
     */
    setVoice(voice) {
        this.setVoiceOptions({ voice: voice });
    }
    
    /**
     * Switch to a specific TTS system
     * @param {string} type - The TTS system to use ('kokoro', 'browser', or 'api')
     * @returns {boolean} - Success status
     */
    switchTTS(type) {
        if (!this.ttsFactory) return false;
        const result = this.ttsFactory.switchTTS(type);
        
        // If the switch was successful, refresh the voice list
        if (result) {
            // Notify listeners that the TTS system changed
            window.dispatchEvent(new CustomEvent('tts-system-changed', {
                detail: { 
                    type,
                    info: this.getTTSInfo()
                }
            }));
        }
        
        return result;
    }
    
    /**
     * Get available TTS systems
     * @returns {Array<string>} - Array of available TTS system IDs
     */
    getAvailableSystems() {
        if (!this.ttsFactory) return [];
        const handlers = this.ttsFactory.getAvailableHandlers();
        return Object.keys(handlers);
    }
    
    /**
     * Get available voices for the active TTS system
     * @returns {Promise<Array>} - Array of voice objects
     */
    async getVoices() {
        if (!this.ttsFactory) return [];
        return this.ttsFactory.getVoices();
    }
    
    /**
     * Is TTS enabled currently
     * @returns {boolean} - Whether TTS is enabled
     */
    isEnabled() {
        if (!this.ttsFactory) return false;
        return this.ttsFactory.isEnabled();
    }
}

// Create the singleton instance
const TTSPlayer = new TTSPlayerModule();

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

// Export the module
export { TTSPlayer };

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