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

class AnimationQueueModule extends BaseModule {
    constructor() {
        super('animation-queue', 'Animation Queue');
        
        // Module dependencies
        this.dependencies = [];
        
        // Queue of scheduled animations/functions
        this.timeoutQueue = [];
        
        // Animation timing properties - use parent's config system
        this.updateConfig({
            speed: 1.0,  // Speed multiplier for delays (1.0 = no scaling, delays are pre-calculated)
            fastForwardEnabled: false
        });
        
        this.delay = 0;   // Current accumulated delay
        
        // Bind methods using parent's bindMethods utility
        this.bindMethods([
            'schedule',
            'fastForward',
            'clearAll',
            'setSpeed',
            'beginFastForward',
            'endFastForward',
            'emitAnimationComplete',
            'cleanupStaleTasks'
        ]);
    }
    
    async initialize() {
        try {
            this.reportProgress(20, "Initializing Animation Queue");

            // Listen for speed changes from UI
            document.addEventListener('animation:speed:change', (event) => {
                if (event.detail && typeof event.detail.speed === 'number') {
                    // Speed from UI is a rate multiplier (0.5-2.0 typically)
                    this.config.speed = event.detail.speed;
                    console.log(`AnimationQueue: Speed updated to ${this.config.speed}`);
                }
            });

            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, with optional TTS synchronization
     * @param {Function} func - Function to execute
     * @param {number} delay - Delay in milliseconds
     * @param {Object} options - Optional parameters including TTS text
     * @returns {number} - Timeout ID for cancellation
     */
    schedule(func, delay, options = {}) {
        if (typeof func !== 'function') {
            console.error('AnimationQueue: Invalid function provided to schedule');
            return -1;
        }
        
        // Adjust delay based on fast-forward or speed settings
        const actualDelay = this.config.fastForwardEnabled ? 0 : Math.max(0, delay * this.config.speed);
        
        // Record the delay for tracking
        this.delay = Math.max(this.delay, delay);
        
        // Create a timeout object
        const timeoutObject = {
            func: func,
            delay: actualDelay,
            timeoutId: null,
            executed: false,
            startTime: Date.now(),

            // Add an execute method that marks the timeout as executed
            execute: function() {
                if (!this.executed) {
                    this.func();
                    this.executed = true;
                }
            }
        };
        
        // Add to queue
        this.timeoutQueue.push(timeoutObject);
        
        // If we're fast forwarding, execute immediately
        if (this.config.fastForwardEnabled) {
            timeoutObject.execute();
            return -1; // No timeout ID since it executed immediately
        }
        
        // Schedule the timeout
        timeoutObject.timeoutId = setTimeout(() => {
            // Execute the function
            timeoutObject.execute();
            
            // Remove from queue
            const index = this.timeoutQueue.indexOf(timeoutObject);
            if (index !== -1) {
                this.timeoutQueue.splice(index, 1);
            }
            
            // If queue is empty and no TTS is speaking, emit animation complete
            if (this.timeoutQueue.length === 0 && true) {
                this.emitAnimationComplete();
            }
            
        }, actualDelay);
        
        return timeoutObject.timeoutId;
    }
    
    /**
     * Emit an animation complete event
     */
    emitAnimationComplete() {
        // Only emit if queue is empty and no TTS is speaking
        if (this.timeoutQueue.length === 0 && true) {
            // Use parent's dispatchEvent method
            this.dispatchEvent('ui:animation:complete', {
                timestamp: Date.now()
            });
        }
    }
    
    /**
     * Clean up any animation tasks that might have been missed
     * (e.g. due to browser tab being inactive)
     */
    cleanupStaleTasks() {
        const now = Date.now();
        const staleTasks = [];
        
        // Find stale tasks
        this.timeoutQueue.forEach(task => {
            // If task has been running for more than 10 seconds, consider it stale
            if (now - task.startTime > 10000 && !task.executed) {
                staleTasks.push(task);
            }
        });
        
        // Execute and remove stale tasks
        staleTasks.forEach(task => {
            console.log('AnimationQueue: Cleaning up stale task');
            
            // Clear the timeout
            if (task.timeoutId !== null) {
                clearTimeout(task.timeoutId);
            }
            
            // Execute the task
            task.execute();
            
            // Remove from queue
            const index = this.timeoutQueue.indexOf(task);
            if (index !== -1) {
                this.timeoutQueue.splice(index, 1);
            }
        });
    }
    
    /**
     * Fast forward all pending animations
     */
    fastForward() {
        if (this.timeoutQueue.length === 0) {
            console.log('AnimationQueue: No animations to fast forward');
            return;
        }

        console.log(`AnimationQueue: Fast forwarding ${this.timeoutQueue.length} pending items`);
        
        // Execute all pending animations immediately
        this.timeoutQueue.forEach(timeout => {
            // Clear the timeout
            if (timeout.timeoutId !== null) {
                clearTimeout(timeout.timeoutId);
                timeout.timeoutId = null;
            }
            
            // Clear TTS flag
            timeout.ttsSpeaking = false;
            
            // Execute the function immediately
            timeout.execute();
        });
        
        // Clear the queue
        this.timeoutQueue = [];
        
        // Reset delay
        this.delay = 0;
        
        // Update config using parent's updateConfig method
        this.updateConfig({ fastForwardEnabled: false });
        
        // Emit animation complete event
        this.emitAnimationComplete();
        
        // Log the fastforward completion
        console.log('AnimationQueue: Fast forward complete');
        
        // Use parent's dispatchEvent method
        this.dispatchEvent('ui:animation:fastforward', { state: false });
    }
    
    /**
     * Begin fast forwarding mode
     */
    beginFastForward() {
        if (this.config.fastForwardEnabled) return;

        // Update config using parent's updateConfig method
        this.updateConfig({ fastForwardEnabled: true });

        // Use parent's dispatchEvent method
        this.dispatchEvent('ui:animation:fastforward', { state: true });

        console.log('AnimationQueue: Fast forward mode activated');
    }
    
    /**
     * End fast forwarding mode
     */
    endFastForward() {
        if (!this.config.fastForwardEnabled) return;
        
        // Update config using parent's updateConfig method
        this.updateConfig({ fastForwardEnabled: false });
        
        // Use parent's dispatchEvent method
        this.dispatchEvent('ui:animation:fastforward', { state: false });
        
        console.log('AnimationQueue: Fast forward mode deactivated');
    }
    
    /**
     * Clear all scheduled animations without executing them
     */
    clearAll() {
        console.log(`Animation Queue: Clearing ${this.timeoutQueue.length} pending items`);
        
        // Clear all timeouts
        this.timeoutQueue.forEach(timeoutObject => {
            if (timeoutObject.timeoutId !== null) {
                clearTimeout(timeoutObject.timeoutId);
            }
        });
        
        // Clear queue
        this.timeoutQueue = [];
        
        // 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;
        }
        
        // Update config using parent's updateConfig method
        this.updateConfig({ speed });
        console.log(`Animation Queue: Speed set to ${speed}`);
    }
    
    /**
     * Get the current animation speed
     * @returns {number} - Current animation speed factor
     */
    getSpeed() {
        return this.config.speed;
    }
    
    /**
     * Check if fast forwarding is active
     * @returns {boolean} - Whether fast forwarding is active
     */
    isFastForwarding() {
        return this.config.fastForwardEnabled;
    }
    
    /**
     * Get current queue length
     * @returns {number} - Number of items in the queue
     */
    getQueueLength() {
        return this.timeoutQueue.length;
    }
    
    /**
     * Get current accumulated delay
     * @returns {number} - Current delay in milliseconds
     */
    getCurrentDelay() {
        return this.delay;
    }
}

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

// Export the module
export { AnimationQueue };
