"""
y4seenx - Text Animation & Effects
Typing effects, color animations, and more!
"""
import time
import sys
from typing import Union
from .gradient import Gradient
from .colors import Color, parse_color


class Write:
    """Text writing effects (like pystyle Write.Input but better!)"""
    
    @staticmethod
    def print(text: str, gradient: Union[Gradient, str, tuple] = None, 
              interval: float = 0.01, end: str = '\n'):
        """
        Print text with typing animation
        
        Args:
            text: Text to print
            gradient: Gradient object, color, or None
            interval: Delay between characters (seconds)
            end: String appended after text
        
        Example:
            Write.print("Hello World!", Presets.FIRE, interval=0.05)
        """
        if gradient:
            if isinstance(gradient, Gradient):
                text = gradient.horizontal(text, reset=False)
            else:
                color = parse_color(gradient)
                text = color.to_ansi() + text
        
        for char in text:
            sys.stdout.write(char)
            sys.stdout.flush()
            time.sleep(interval)
        
        sys.stdout.write("\033[0m" + end)
        sys.stdout.flush()
    
    @staticmethod
    def input(prompt: str, gradient: Union[Gradient, str, tuple] = None,
              interval: float = 0.01) -> str:
        """
        Input with colored/animated prompt
        
        Example:
            choice = Write.input("Select option: ", Presets.BLUE_CYAN)
        """
        Write.print(prompt, gradient, interval, end='')
        return input()
    
    @staticmethod
    def input_fast(prompt: str, gradient: Union[Gradient, str, tuple] = None) -> str:
        """Fast input without animation (convenience method)"""
        if gradient:
            if isinstance(gradient, Gradient):
                prompt = gradient.horizontal(prompt)
            else:
                color = parse_color(gradient)
                prompt = color.to_ansi() + prompt + "\033[0m"
        return input(prompt)


class Animate:
    """Advanced text animations"""
    
    @staticmethod
    def wave(text: str, gradient: Gradient, cycles: int = 3, speed: float = 0.05):
        """
        Animated wave effect through text
        
        Args:
            text: Text to animate
            gradient: Gradient to use
            cycles: Number of wave cycles
            speed: Animation speed
        """
        import os
        
        for cycle in range(cycles):
            for offset in range(len(text) + 1):
                # Clear line
                sys.stdout.write('\r' + ' ' * (len(text) + 10) + '\r')
                
                # Create offset gradient effect
                output = ""
                for i, char in enumerate(text):
                    if char == ' ':
                        output += char
                    else:
                        pos = ((i + offset) % len(text)) / len(text)
                        color = gradient.get_color_at(pos)
                        output += color.to_ansi() + char
                
                sys.stdout.write(output + "\033[0m")
                sys.stdout.flush()
                time.sleep(speed)
        
        print()  # New line after animation
    
    @staticmethod
    def pulse(text: str, color: Union[str, tuple, Color], 
              pulses: int = 3, speed: float = 0.1):
        """
        Pulse effect (fade in/out)
        
        Args:
            text: Text to pulse
            color: Base color
            pulses: Number of pulses
            speed: Animation speed
        """
        base_color = parse_color(color)
        
        for _ in range(pulses):
            # Fade in
            for brightness in range(0, 11):
                factor = brightness / 10.0
                h, s, l = base_color.to_hsl()
                l = l * factor
                pulse_color = Color.from_hsl(h, s, min(100, l))
                
                sys.stdout.write('\r' + pulse_color.to_ansi() + text + "\033[0m")
                sys.stdout.flush()
                time.sleep(speed)
            
            # Fade out
            for brightness in range(10, -1, -1):
                factor = brightness / 10.0
                h, s, l = base_color.to_hsl()
                l = l * factor
                pulse_color = Color.from_hsl(h, s, min(100, l))
                
                sys.stdout.write('\r' + pulse_color.to_ansi() + text + "\033[0m")
                sys.stdout.flush()
                time.sleep(speed)
        
        print()
    
    @staticmethod
    def rainbow_cycle(text: str, cycles: int = 3, speed: float = 0.05):
        """
        Cycle through rainbow colors
        """
        from .gradient import Presets
        
        for _ in range(cycles):
            for hue in range(0, 360, 10):
                color = Color.from_hsv(hue, 100, 100)
                sys.stdout.write('\r' + color.to_ansi() + text + "\033[0m")
                sys.stdout.flush()
                time.sleep(speed)
        
        print()


class Box:
    """Create beautiful boxes around text"""
    
    @staticmethod
    def simple(text: str, gradient: Gradient = None, padding: int = 1) -> str:
        """
        Create a simple box around text
        
        Example:
            print(Box.simple("Hello World!", Presets.FIRE))
        """
        lines = text.split('\n')
        max_length = max(len(line) for line in lines) if lines else 0
        
        # Create box
        top = "┌" + "─" * (max_length + padding * 2) + "┐"
        bottom = "└" + "─" * (max_length + padding * 2) + "┘"
        
        boxed_lines = [top]
        for line in lines:
            padded = " " * padding + line.ljust(max_length) + " " * padding
            boxed_lines.append("│" + padded + "│")
        boxed_lines.append(bottom)
        
        result = '\n'.join(boxed_lines)
        
        if gradient:
            result = gradient.horizontal(result)
        
        return result
    
    @staticmethod
    def double(text: str, gradient: Gradient = None, padding: int = 1) -> str:
        """Create a double-line box"""
        lines = text.split('\n')
        max_length = max(len(line) for line in lines) if lines else 0
        
        top = "╔" + "═" * (max_length + padding * 2) + "╗"
        bottom = "╚" + "═" * (max_length + padding * 2) + "╝"
        
        boxed_lines = [top]
        for line in lines:
            padded = " " * padding + line.ljust(max_length) + " " * padding
            boxed_lines.append("║" + padded + "║")
        boxed_lines.append(bottom)
        
        result = '\n'.join(boxed_lines)
        
        if gradient:
            result = gradient.horizontal(result)
        
        return result
