"""
Rain weather engine.

Creates animated falling rain particles with realistic movement.
"""

import random
from typing import List

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


class RainEngine(BaseWeatherEngine):
    """
    Rain simulation engine.
    
    Creates falling rain particles with wind drift and variable intensity.
    """
    
    # Rain particle characters (various rain styles)
    RAIN_CHARS = ['|', '│', '┃', '╽', '╿', '⸽']
    RAIN_CHARS_HEAVY = ['┃', '║', '┋', '┇']
    RAIN_SPLASH_CHARS = ['·', '°', '•', '∘', '○']
    
    def __init__(self, config: EngineConfig = None):
        super().__init__(config)
        self.wind_direction = random.uniform(-0.3, 0.3)
        self.splash_particles: List[Particle] = []
        
    def get_particle_chars(self) -> List[str]:
        """Return rain character set based on intensity."""
        if self.config.intensity > 1.5:
            return self.RAIN_CHARS_HEAVY
        return self.RAIN_CHARS
    
    def initialize_particles(self) -> None:
        """Initialize rain particles across the screen."""
        particle_count = int(
            self.config.width * self.config.height * 0.02 * self.config.intensity
        )
        self.particles = []
        
        for _ in range(particle_count):
            self.particles.append(self._spawn_raindrop())
    
    def _spawn_raindrop(self, from_top: bool = False) -> Particle:
        """Spawn a new raindrop."""
        chars = self.get_particle_chars()
        return Particle(
            x=random.uniform(0, self.config.width),
            y=0 if from_top else random.uniform(0, self.config.height),
            char=random.choice(chars),
            speed=random.uniform(0.8, 1.5) * self.config.intensity,
            drift=self.wind_direction + random.uniform(-0.05, 0.05),
            color=self._get_rain_color()
        )
    
    def _get_rain_color(self) -> str:
        """Get color based on theme or default."""
        theme_colors = self.config.theme.get('rain_colors', ['cyan', 'blue', 'white'])
        return random.choice(theme_colors) if theme_colors else 'cyan'
    
    def _spawn_splash(self, x: float, y: float) -> List[Particle]:
        """Create splash particles when rain hits the ground."""
        splashes = []
        for _ in range(random.randint(1, 3)):
            splashes.append(Particle(
                x=x + random.uniform(-1, 1),
                y=y,
                char=random.choice(self.RAIN_SPLASH_CHARS),
                speed=-0.3,  # Splashes move up briefly
                drift=random.uniform(-0.5, 0.5),
                color='white'
            ))
        return splashes
    
    def update_particles(self) -> None:
        """Update all rain particles."""
        new_particles = []
        
        for particle in self.particles:
            # Update position
            particle.y += particle.speed
            particle.x += particle.drift
            
            # Check if particle hit the ground
            if particle.y >= self.config.height - 1:
                # Create splash effect
                if random.random() < 0.3 * self.config.intensity:
                    self.splash_particles.extend(
                        self._spawn_splash(particle.x, particle.y)
                    )
                # Respawn from top
                new_particles.append(self._spawn_raindrop(from_top=True))
            elif particle.x < 0 or particle.x >= self.config.width:
                # Respawn if out of horizontal bounds
                new_particles.append(self._spawn_raindrop(from_top=True))
            else:
                new_particles.append(particle)
        
        # Update splash particles
        new_splashes = []
        for splash in self.splash_particles:
            splash.y += splash.speed
            splash.speed += 0.1  # Gravity
            splash.x += splash.drift
            
            if splash.speed < 0.5 and splash.y > 0:
                new_splashes.append(splash)
        
        self.splash_particles = new_splashes
        self.particles = new_particles + self.splash_particles
    
    def set_wind(self, direction: float) -> None:
        """Set wind direction (-1.0 to 1.0)."""
        self.wind_direction = max(-1.0, min(1.0, direction))
