"""
Thunder/Storm weather engine.

Creates lightning flashes and storm effects with optional sound triggers.
"""

import random
import sys
from typing import List, Optional

from soracli.engines.base import BaseWeatherEngine, Particle, EngineConfig
from soracli.engines.rain import RainEngine


class ThunderEngine(BaseWeatherEngine):
    """
    Thunderstorm simulation engine.
    
    Combines heavy rain with lightning flashes and thunder effects.
    """
    
    # Lightning bolt characters
    LIGHTNING_CHARS = ['╲', '╱', '│', '┃', '⚡', '϶']
    
    # Thunder rumble patterns for visual effect
    RUMBLE_PATTERNS = [
        '▄▀▄▀▄▀',
        '░▒▓█▓▒░',
        '┌─┐│└─┘',
    ]
    
    def __init__(self, config: EngineConfig = None):
        super().__init__(config)
        self.rain_engine = RainEngine(config)
        self.lightning_active = False
        self.lightning_frames = 0
        self.flash_intensity = 0.0
        self.next_lightning = random.randint(20, 100)
        self.frame_count = 0
        self.lightning_bolt: List[tuple] = []
        
    def get_particle_chars(self) -> List[str]:
        """Return character set for rain (delegated to rain engine)."""
        return self.rain_engine.get_particle_chars()
    
    def initialize_particles(self) -> None:
        """Initialize storm particles."""
        # Initialize heavy rain
        self.rain_engine.config = self.config
        self.rain_engine.config.intensity = max(1.5, self.config.intensity)
        self.rain_engine.initialize_particles()
        self.particles = self.rain_engine.particles
        
    def _generate_lightning_bolt(self) -> List[tuple]:
        """Generate a zigzag lightning bolt path."""
        bolt = []
        x = random.randint(self.config.width // 4, 3 * self.config.width // 4)
        y = 0
        
        while y < self.config.height - 1:
            bolt.append((x, y))
            
            # Zigzag pattern
            direction = random.choice([-1, 0, 1])
            x += direction
            x = max(0, min(self.config.width - 1, x))
            y += 1
            
            # Occasionally branch
            if random.random() < 0.1 and len(bolt) > 5:
                branch_x = x
                branch_y = y
                for _ in range(random.randint(3, 7)):
                    branch_x += random.choice([-1, 1])
                    branch_y += 1
                    if 0 <= branch_x < self.config.width and branch_y < self.config.height:
                        bolt.append((branch_x, branch_y))
        
        return bolt
    
    def _trigger_lightning(self) -> None:
        """Trigger a lightning flash."""
        self.lightning_active = True
        self.lightning_frames = random.randint(2, 5)
        self.flash_intensity = 1.0
        self.lightning_bolt = self._generate_lightning_bolt()
        
        # Trigger sound if enabled
        if self.config.sound_enabled:
            self._play_thunder_sound()
    
    def _play_thunder_sound(self) -> None:
        """Attempt to play thunder sound (cross-platform)."""
        try:
            # Terminal bell as fallback
            print('\a', end='', file=sys.stderr)
        except Exception:
            pass  # Sound is optional
    
    def update_particles(self) -> None:
        """Update storm particles and lightning."""
        self.frame_count += 1
        
        # Update rain
        self.rain_engine.particles = self.particles
        self.rain_engine.update_particles()
        self.particles = self.rain_engine.particles
        
        # Handle lightning timing
        if self.frame_count >= self.next_lightning and not self.lightning_active:
            self._trigger_lightning()
            self.next_lightning = self.frame_count + random.randint(30, 150)
        
        # Update lightning state
        if self.lightning_active:
            self.lightning_frames -= 1
            self.flash_intensity *= 0.6
            
            if self.lightning_frames <= 0:
                self.lightning_active = False
                self.lightning_bolt = []
    
    def render_frame(self) -> str:
        """Render the storm frame with lightning effects."""
        # Create empty buffer
        buffer = [[' ' for _ in range(self.config.width)] 
                  for _ in range(self.config.height)]
        
        # Place rain particles
        for particle in self.particles:
            x = int(particle.x)
            y = int(particle.y)
            if 0 <= x < self.config.width and 0 <= y < self.config.height:
                buffer[y][x] = particle.char
        
        # Draw lightning bolt
        if self.lightning_active and self.lightning_bolt:
            for x, y in self.lightning_bolt:
                if 0 <= x < self.config.width and 0 <= y < self.config.height:
                    buffer[y][x] = random.choice(self.LIGHTNING_CHARS)
        
        # Apply flash effect to the output
        frame = self.renderer.render_buffer(
            buffer, 
            self.particles, 
            self.config.theme
        )
        
        if self.lightning_active:
            frame = self._apply_flash_effect(frame)
        
        return frame
    
    def _apply_flash_effect(self, frame: str) -> str:
        """Apply screen flash effect during lightning."""
        # Use ANSI reverse video for flash effect
        intensity = self.flash_intensity
        
        if intensity > 0.7:
            # Full flash - invert colors
            return f"\033[7m{frame}\033[27m"
        elif intensity > 0.3:
            # Partial flash - bright background
            return f"\033[48;5;231m{frame}\033[49m"
        
        return frame
    
    def force_lightning(self) -> None:
        """Force an immediate lightning strike (for demo mode)."""
        self._trigger_lightning()
    
    def set_storm_intensity(self, intensity: float) -> None:
        """Set overall storm intensity."""
        self.set_intensity(intensity)
        self.rain_engine.set_intensity(intensity * 1.5)
