/**
 * Animation Queue Module
 * Handles scheduling and executing animations with proper resource management
 * and synchronization with TTS
 */
import { BaseModule } from './base-module.js';
import { moduleRegistry } from './module-registry.js';
import { ModuleEvent } from './base-module.js'; // Add this import

class AnimationQueueModule extends BaseModule {
    constructor() {
        super('animation-queue', 'Animation Queue');
        
        // Queue of scheduled animations/functions
        this.queue = [];
        
        // Animation timing properties
        this.speed = 0.05;  // Base animation speed (seconds per character)
        this.delay = 0;     // Current accumulated delay
        
        // Module dependencies
        this.dependencies = ['tts'];
        this.tts = null;    // TTS module reference
        
        // Fast-forwarding state
        this.isFastForwarding = false;
        
        // Bind methods
        this.schedule = this.schedule.bind(this);
        this.fastForward = this.fastForward.bind(this);
        this.clearAll = this.clearAll.bind(this);
        this.setSpeed = this.setSpeed.bind(this);
    }
    
    async waitForDependencies() {
        try {
            // Wait for TTS module to be available
            this.tts = moduleRegistry.getModule('tts');
            
            if (!this.tts) {
                console.warn("TTS module not ready, Animation Queue will have limited functionality");
                return true; // Continue anyway
            }
            
            return true;
        } catch (error) {
            console.error("Error waiting for Animation Queue dependencies:", error);
            return false;
        }
    }
    
    async initialize() {
        try {
            // Nothing special to initialize here
            this.reportProgress(100, "Animation Queue ready");
            return true;
        } catch (error) {
            console.error("Error initializing Animation Queue:", error);
            return false;
        }
    }
    
    /**
     * Schedule a function to execute after a delay
     * @param {Function} func - Function to execute
     * @param {number} delay - Delay in milliseconds
     * @param {...any} args - Arguments to pass to the function
     * @returns {Object} - Timeout object that can be used to cancel
     */
    schedule(func, delay, ...args) {
        if (typeof func !== 'function') {
            console.error('Animation Queue: Not a function passed to schedule');
            return null;
        }
        
        // Create timeout object with execute method
        const timeoutObject = {
            execute: () => {
                try {
                    func(...args);
                } catch (error) {
                    console.error('Error executing scheduled function:', error);
                }
            },
            timeoutId: null,
            createdAt: Date.now(),
            delay: delay
        };
        
        // Apply speed factor to the delay
        const adjustedDelay = delay * this.speed;
        
        // Schedule execution
        timeoutObject.timeoutId = setTimeout(() => {
            // Execute the function
            timeoutObject.execute();
            
            // Remove from queue
            const index = this.queue.indexOf(timeoutObject);
            if (index !== -1) {
                this.queue.splice(index, 1);
            }
        }, adjustedDelay);
        
        // Add to queue
        this.queue.push(timeoutObject);
        
        // Update current total delay
        this.delay = adjustedDelay + delay;
        
        return timeoutObject;
    }
    
    /**
     * Fast-forward all pending animations
     */
    fastForward() {
        console.log(`Animation Queue: Fast-forwarding ${this.queue.length} pending items`);
        
        // Stop TTS if playing
        if (this.tts) {
            this.tts.stop();
        }
        
        // Execute and clear all timeouts
        const queueCopy = [...this.queue]; // Make a copy to avoid modification during iteration
        
        queueCopy.forEach(timeoutObject => {
            // Clear timeout
            if (timeoutObject.timeoutId !== null) {
                clearTimeout(timeoutObject.timeoutId);
            }
            
            // Execute immediately
            timeoutObject.execute();
        });
        
        // Clear queue
        this.queue = [];
        
        // Reset delay
        this.delay = 0;
        
        // Use direct DOM event dispatch instead of this.dispatchEvent
        document.dispatchEvent(new CustomEvent('animations:fastForwarded', {
            detail: { moduleId: this.id }
        }));
    }
    
    /**
     * Clear all scheduled animations without executing them
     */
    clearAll() {
        console.log(`Animation Queue: Clearing ${this.queue.length} pending items`);
        
        // Clear all timeouts
        this.queue.forEach(timeoutObject => {
            if (timeoutObject.timeoutId !== null) {
                clearTimeout(timeoutObject.timeoutId);
            }
        });
        
        // Clear queue
        this.queue = [];
        
        // Reset delay
        this.delay = 0;
    }
    
    /**
     * Set the animation speed
     * @param {number} speed - Animation speed factor (lower is faster)
     */
    setSpeed(speed) {
        if (typeof speed !== 'number' || speed <= 0) {
            console.error('Animation Queue: Invalid speed value');
            return;
        }
        
        this.speed = speed;
        console.log(`Animation Queue: Speed set to ${speed}`);
    }
    
    /**
     * Get current queue length
     * @returns {number} - Number of items in the queue
     */
    getQueueLength() {
        return this.queue.length;
    }
    
    /**
     * Get current accumulated delay
     * @returns {number} - Current delay in milliseconds
     */
    getCurrentDelay() {
        return this.delay;
    }
}

// Create the singleton instance
const AnimationQueue = new AnimationQueueModule();

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

// Export the module
export { AnimationQueue };

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