"""
y4seenx - Ultimate Gradient Engine
Supports horizontal, vertical, diagonal, radial, and custom gradients
"""
from typing import List, Union, Tuple
from .colors import Color, parse_color
import math


class Gradient:
    """Ultimate Gradient Generator"""
    
    def __init__(self, *colors: Union[str, Tuple, Color]):
        """
        Initialize gradient with any number of colors
        Example: Gradient('#FF0000', '#00FF00', '#0000FF')
        """
        if len(colors) < 2:
            raise ValueError("Gradient requires at least 2 colors")
        self.colors = [parse_color(c) for c in colors]
    
    def get_color_at(self, position: float) -> Color:
        """
        Get color at specific position in gradient (0.0 to 1.0)
        """
        position = max(0.0, min(1.0, position))
        
        if len(self.colors) == 2:
            return self.colors[0].interpolate(self.colors[1], position)
        
        # For multiple colors, find the two colors to interpolate between
        segment_size = 1.0 / (len(self.colors) - 1)
        segment_index = int(position / segment_size)
        
        if segment_index >= len(self.colors) - 1:
            return self.colors[-1]
        
        local_position = (position - segment_index * segment_size) / segment_size
        return self.colors[segment_index].interpolate(self.colors[segment_index + 1], local_position)
    
    def horizontal(self, text: str, reset: bool = True) -> str:
        """
        Apply horizontal gradient to text
        Example: Gradient('#FF0000', '#0000FF').horizontal('Hello World')
        """
        if not text:
            return text
        
        # Remove existing ANSI codes
        clean_text = self._strip_ansi(text)
        lines = clean_text.split('\n')
        result = []
        
        for line in lines:
            if not line:
                result.append(line)
                continue
            
            colored_line = ""
            line_length = len(line)
            
            for i, char in enumerate(line):
                if char == ' ':
                    colored_line += char
                else:
                    position = i / max(1, line_length - 1)
                    color = self.get_color_at(position)
                    colored_line += color.to_ansi() + char
            
            if reset:
                colored_line += "\033[0m"
            result.append(colored_line)
        
        return '\n'.join(result)
    
    def vertical(self, text: str, reset: bool = True) -> str:
        """
        Apply vertical gradient to text
        Example: Gradient('#FF0000', '#0000FF').vertical('Hello\\nWorld')
        """
        if not text:
            return text
        
        clean_text = self._strip_ansi(text)
        lines = clean_text.split('\n')
        
        if not lines:
            return text
        
        result = []
        total_lines = len(lines)
        
        for i, line in enumerate(lines):
            position = i / max(1, total_lines - 1)
            color = self.get_color_at(position)
            colored_line = color.to_ansi() + line
            if reset:
                colored_line += "\033[0m"
            result.append(colored_line)
        
        return '\n'.join(result)
    
    def diagonal(self, text: str, reset: bool = True) -> str:
        """
        Apply diagonal gradient to text (top-left to bottom-right)
        """
        if not text:
            return text
        
        clean_text = self._strip_ansi(text)
        lines = clean_text.split('\n')
        result = []
        
        total_lines = len(lines)
        max_length = max(len(line) for line in lines) if lines else 0
        
        for line_idx, line in enumerate(lines):
            colored_line = ""
            for char_idx, char in enumerate(line):
                if char == ' ':
                    colored_line += char
                else:
                    # Diagonal position calculation
                    position = (line_idx / max(1, total_lines - 1) + 
                               char_idx / max(1, max_length - 1)) / 2
                    color = self.get_color_at(position)
                    colored_line += color.to_ansi() + char
            
            if reset:
                colored_line += "\033[0m"
            result.append(colored_line)
        
        return '\n'.join(result)
    
    def radial(self, text: str, reset: bool = True, center: Tuple[float, float] = (0.5, 0.5)) -> str:
        """
        Apply radial gradient from center
        center: (x, y) position from 0.0 to 1.0
        """
        if not text:
            return text
        
        clean_text = self._strip_ansi(text)
        lines = clean_text.split('\n')
        result = []
        
        total_lines = len(lines)
        max_length = max(len(line) for line in lines) if lines else 0
        
        center_y = center[1] * total_lines
        center_x = center[0] * max_length
        
        max_distance = math.sqrt((max_length/2)**2 + (total_lines/2)**2)
        
        for line_idx, line in enumerate(lines):
            colored_line = ""
            for char_idx, char in enumerate(line):
                if char == ' ':
                    colored_line += char
                else:
                    # Calculate distance from center
                    dx = char_idx - center_x
                    dy = line_idx - center_y
                    distance = math.sqrt(dx**2 + dy**2)
                    position = min(1.0, distance / max_distance)
                    
                    color = self.get_color_at(position)
                    colored_line += color.to_ansi() + char
            
            if reset:
                colored_line += "\033[0m"
            result.append(colored_line)
        
        return '\n'.join(result)
    
    @staticmethod
    def _strip_ansi(text: str) -> str:
        """Remove ANSI escape codes from text"""
        import re
        ansi_escape = re.compile(r'\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])')
        return ansi_escape.sub('', text)
    
    def __repr__(self):
        return f"Gradient({', '.join([c.to_hex() for c in self.colors])})"


# Preset gradients for convenience
class Presets:
    """Pre-defined beautiful gradients"""
    
    # Basic color transitions
    RED_BLUE = Gradient('#FF0000', '#0000FF')
    RED_GREEN = Gradient('#FF0000', '#00FF00')
    BLUE_CYAN = Gradient('#0000FF', '#00FFFF')
    GREEN_WHITE = Gradient('#00FF00', '#FFFFFF')
    PURPLE_BLUE = Gradient('#800080', '#0000FF')
    RED_YELLOW = Gradient('#FF0000', '#FFFF00')
    
    # Popular gradients
    FIRE = Gradient('#FF0000', '#FF4500', '#FFA500', '#FFFF00')
    OCEAN = Gradient('#000080', '#0000FF', '#00BFFF', '#00FFFF')
    FOREST = Gradient('#013220', '#228B22', '#32CD32', '#90EE90')
    SUNSET = Gradient('#FF6B6B', '#FFA500', '#FFD700', '#FFF68F')
    RAINBOW = Gradient('#FF0000', '#FF7F00', '#FFFF00', '#00FF00', '#0000FF', '#4B0082', '#9400D3')
    
    # Neon gradients
    NEON_PINK = Gradient('#FF006E', '#FF6EC7', '#FFAFCC')
    NEON_BLUE = Gradient('#00D9FF', '#0099FF', '#0066FF')
    NEON_GREEN = Gradient('#39FF14', '#00FF7F', '#00FA9A')
    
    # Pastel gradients
    PASTEL_RAINBOW = Gradient('#FFB3BA', '#FFDFBA', '#FFFFBA', '#BAFFC9', '#BAE1FF')
    PASTEL_PINK = Gradient('#FFE5EC', '#FFC2D1', '#FF85A1')
    
    # Dark mode friendly
    DARK_PURPLE = Gradient('#2D1B4E', '#5B2C6F', '#8B4789')
    DARK_BLUE = Gradient('#0A1931', '#185ADB', '#FFC947')
    
    # Cyberpunk
    CYBERPUNK = Gradient('#FF00FF', '#00FFFF', '#FF0080')
    MATRIX = Gradient('#003300', '#00FF00', '#00FF00')
    
    # Monochrome
    GRAY_SCALE = Gradient('#000000', '#808080', '#FFFFFF')
    BLACK_WHITE = Gradient('#000000', '#FFFFFF')
