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

class UIEffectsModule extends BaseModule {
    constructor() {
        super('ui-effects', 'UI Effects');
        
        // No external dependencies
        this.dependencies = ['ui-display-handler'];
        
        // Effects state
        this.activeEffects = new Map();
        this.ambientEffectsActive = false;
        
        // Effects configuration - use the config object from BaseModule
        this.updateConfig({
            candleFlicker: {
                intensity: 0.5,
                speed: 0.8
            },
            textShadow: {
                enabled: true,
                color: 'rgba(0, 0, 0, 0.5)'
            },
            backgroundEffects: {
                enabled: true
            }
        });
        
        // Use bindMethods from parent class
        this.bindMethods([
            'updateCandleEffect',
            'setupEffectElements',
            'createEffectsOverlay',
            'createCandleEffect',
            'createLightingElement',
            'setupAmbientEffects',
            'setupCandleFlickerEffect',
            'startAmbientEffects',
            'stopAmbientEffects',
            'applyEffect',
            'applyShakeEffect',
            'applyFlashEffect',
            'processCommand',
            'handleLightingAnimationEnd'
        ]);
        
        console.log('UIEffects: Constructor initialized');
    }

    async initialize() {
        this.reportProgress(0, 'Initializing UI Effects');
        
        try {
            this.reportProgress(30, 'Setting up effect elements');
            
            // Create or get effect elements
            this.setupEffectElements();
            
            this.reportProgress(60, 'Preparing ambient effects');
            
            // Set up ambient effect animations
            this.setupAmbientEffects();
            
            // Start ambient effects immediately after initialization
            this.startAmbientEffects();
            
            this.reportProgress(100, 'UI Effects ready');
            
            // Use the parent's dispatchEvent method
            this.dispatchEvent('ui:effects:ready', {});
            
            return true;
        } catch (error) {
            console.error('Error initializing UI Effects:', error);
            this.changeState('ERROR');
            return false;
        }
    }
    
    setupEffectElements() {
        console.log('UIEffects: Setting up effect elements');
        // Create overlay for effects if it doesn't exist
        this.effectsOverlay = document.getElementById('effects-overlay') || this.createEffectsOverlay();
        
        // Create candle effect element
        this.candleEffectElement = document.getElementById('candle-effect') || this.createCandleEffect();
        
        // Ensure lighting element exists
        this.lightingElement = document.getElementById('lighting') || this.createLightingElement();
    }
    
    createEffectsOverlay() {
        const overlay = document.createElement('div');
        overlay.id = 'effects-overlay';
        overlay.className = 'effects-overlay';
        document.body.appendChild(overlay);
        return overlay;
    }
    
    createCandleEffect() {
        const candleEffect = document.createElement('div');
        candleEffect.id = 'candle-effect';
        candleEffect.className = 'candle-effect';
        if (this.effectsOverlay) {
            this.effectsOverlay.appendChild(candleEffect);
        } else {
            document.body.appendChild(candleEffect);
        }
        return candleEffect;
    }
    
    createLightingElement() {
        const lighting = document.createElement('div');
        lighting.id = 'lighting';
        document.body.appendChild(lighting);
        return lighting;
    }
    
    setupAmbientEffects() {
        // Initialize candle flicker effect
        if (this.candleEffectElement && this.config.candleFlicker.enabled !== false) {
            this.setupCandleFlickerEffect();
        }
    }
    
    setupCandleFlickerEffect() {
        // Store the animation frame ID for later cancellation
        this.candleAnimationId = null;
        
        // Add animation end event listener to create continuous random animations
        if (this.lightingElement) {
            this.lightingElement.addEventListener('animationend', this.handleLightingAnimationEnd.bind(this));
        }
    }
    
    /**
     * Handle the end of a lighting animation by setting a new random duration
     * @param {AnimationEvent} event - The animation end event
     */
    handleLightingAnimationEnd(event) {
        if (!this.lightingElement || !this.ambientEffectsActive) return;
        
        // Generate a random duration between 0.5 and 4 seconds
        const randomDuration = Math.random() * 3.5 + 0.5;
        
        // Toggle between grow and shrink animations
        const previousAnimation = event.animationName;
        
        if (previousAnimation === 'gradient-animation-grow') {
            this.lightingElement.style.animation = `gradient-animation-shrink ${randomDuration}s 1`;
        } else {
            this.lightingElement.style.animation = `gradient-animation-grow ${randomDuration}s 1`;
        }
    }
    
    updateCandleEffect() {
        if (!this.candleEffectElement || !this.ambientEffectsActive) return;
        
        const { intensity, speed } = this.config.candleFlicker;
        
        // Create subtle random flickering effect
        const flickerAmount = Math.random() * intensity;
        const opacity = 0.2 + flickerAmount * 0.2;
        
        this.candleEffectElement.style.opacity = opacity;
        
        // Schedule next update
        this.candleAnimationId = requestAnimationFrame(this.updateCandleEffect);
    }
    
    // Public methods
    
    startAmbientEffects() {
        if (this.ambientEffectsActive) return;
        
        this.ambientEffectsActive = true;
        
        // Start candle flicker
        if (this.candleEffectElement) {
            this.updateCandleEffect();
        }
        
        // Apply lighting animation with initial random duration
        if (this.lightingElement) {
            const initialDuration = Math.random() * 3.5 + 0.5;
            this.lightingElement.style.animation = `gradient-animation-shrink ${initialDuration}s 1`;
        }
    }
    
    stopAmbientEffects() {
        this.ambientEffectsActive = false;
        
        // Stop candle flicker
        if (this.candleAnimationId) {
            cancelAnimationFrame(this.candleAnimationId);
            this.candleAnimationId = null;
        }
        
        // Stop lighting animation
        if (this.lightingElement) {
            this.lightingElement.style.animation = '';
        }
    }
    
    applyEffect(effectName, options = {}) {
        switch (effectName) {
            case 'shake':
                return this.applyShakeEffect(options);
            case 'flash':
                return this.applyFlashEffect(options);
            default:
                console.warn(`Unknown effect: ${effectName}`);
                return null;
        }
    }
    
    applyShakeEffect(options = {}) {
        const target = options.target || document.getElementById('book');
        if (!target) return null;
        
        const intensity = options.intensity || 'medium';
        const duration = options.duration || 500;
        
        // Store original styles
        const originalTransition = target.style.transition;
        const originalTransform = target.style.transform;
        
        // Apply the shake animation
        target.style.transition = `transform ${duration}ms ease`;
        target.style.transform = 'translate(0, 0)';
        target.style.animation = `shake ${duration}ms 1`;
        
        // Return to normal after animation
        const effectId = setTimeout(() => {
            target.style.transition = originalTransition;
            target.style.transform = originalTransform;
            target.style.animation = '';
            this.activeEffects.delete(effectId);
        }, duration);
        
        this.activeEffects.set(effectId, { name: 'shake', target });
        return effectId;
    }
    
    applyFlashEffect(options = {}) {
        const color = options.color || 'white';
        const duration = options.duration || 300;
        
        // Create flash overlay if not exists
        let flashOverlay = document.getElementById('flash-overlay');
        if (!flashOverlay) {
            flashOverlay = document.createElement('div');
            flashOverlay.id = 'flash-overlay';
            flashOverlay.style.position = 'fixed';
            flashOverlay.style.top = '0';
            flashOverlay.style.left = '0';
            flashOverlay.style.width = '100%';
            flashOverlay.style.height = '100%';
            flashOverlay.style.pointerEvents = 'none';
            flashOverlay.style.zIndex = '9999';
            flashOverlay.style.opacity = '0';
            flashOverlay.style.transition = `opacity ${duration / 2}ms ease-in-out`;
            document.body.appendChild(flashOverlay);
        }
        
        // Set color and make visible
        flashOverlay.style.backgroundColor = color;
        
        // Start animation
        setTimeout(() => { flashOverlay.style.opacity = '0.8'; }, 10);
        
        const effectId = setTimeout(() => {
            flashOverlay.style.opacity = '0';
            this.activeEffects.delete(effectId);
            
            // Remove element after fade out
            setTimeout(() => {
                if (flashOverlay.parentNode) {
                    flashOverlay.parentNode.removeChild(flashOverlay);
                }
            }, duration / 2);
        }, duration / 2);
        
        this.activeEffects.set(effectId, { name: 'flash' });
        return effectId;
    }
    
    processCommand(command) {
        switch (command.action) {
            case 'apply':
                return this.applyEffect(command.effect, command.options);
            case 'cancel':
                const effectId = command.effectId;
                if (this.activeEffects.has(effectId)) {
                    clearTimeout(effectId);
                    this.activeEffects.delete(effectId);
                }
                break;
            case 'ambient':
                if (command.state === 'start') {
                    this.startAmbientEffects();
                } else if (command.state === 'stop') {
                    this.stopAmbientEffects();
                }
                break;
            default:
                console.warn(`Unknown effect command: ${command.action}`);
        }
    }
}

// Create the singleton instance
const uiEffects = new UIEffectsModule();

// Export the module
export { uiEffects as UIEffects };
