from .ImageManipulation import ImageManipulation
from ImageContainer import ImageContainer
from typing import Any, List
from PIL import ImageDraw, ImageFont
import os


class AddText(ImageManipulation):
    def getManipulationName(self) -> str:
        return "Add Text"

    def getParameters(self) -> List[str]:
        return ["text", "x", "y", "font_size", "color"]

    def manipulateImage(self, image: ImageContainer, parameters: Any) -> None:
        if image is None or image.getImage() is None:
            return
        
        pil_img = image.getImage()
        
        # Default parameters
        text = "Hello"
        x = 10
        y = 10
        font_size = 40
        color = (0, 0, 0)  # Default black
        
        # Extract parameters
        if isinstance(parameters, dict):
            if parameters.get("text") is not None:
                text = str(parameters.get("text"))
            if parameters.get("x") is not None:
                x = int(parameters.get("x"))
            if parameters.get("y") is not None:
                y = int(parameters.get("y"))
            if parameters.get("font_size") is not None:
                font_size = int(parameters.get("font_size"))
            if parameters.get("color") is not None:
                # Handle color as tuple, string, or hex
                color_param = parameters.get("color")
                if isinstance(color_param, tuple):
                    color = color_param
                elif isinstance(color_param, str):
                    # Try to parse hex color (#RRGGBB) or RGB string
                    if color_param.startswith("#"):
                        color = tuple(int(color_param[i:i+2], 16) for i in (1, 3, 5))
                    elif color_param.startswith("rgb"):
                        # Parse "rgb(r,g,b)" format
                        color_str = color_param.strip("rgb()")
                        color = tuple(int(c.strip()) for c in color_str.split(","))
                    else:
                        # Try common color names
                        color_map = {
                            "black": (0, 0, 0),
                            "white": (255, 255, 255),
                            "red": (255, 0, 0),
                            "green": (0, 255, 0),
                            "blue": (0, 0, 255),
                            "yellow": (255, 255, 0),
                            "cyan": (0, 255, 255),
                            "magenta": (255, 0, 255),
                        }
                        color = color_map.get(color_param.lower(), (0, 0, 0))
                else:
                    color = (0, 0, 0)
        
        # Create a copy to draw on
        img_copy = pil_img.copy()
        draw = ImageDraw.Draw(img_copy)
        
        # Try to load a default font, fallback to default if not available
        try:
            # Try to use a TrueType font (common system fonts)
            font_paths = [
                "/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf",
                "/usr/share/fonts/truetype/liberation/LiberationSans-Regular.ttf",
                "/System/Library/Fonts/Helvetica.ttc",
                "C:/Windows/Fonts/arial.ttf",
            ]
            font = None
            for path in font_paths:
                if os.path.exists(path):
                    try:
                        font = ImageFont.truetype(path, font_size)
                        break
                    except:
                        continue
            # If no font found, use default
            if font is None:
                font = ImageFont.load_default()
        except:
            font = ImageFont.load_default()
        
        # Draw the text
        draw.text((x, y), text, fill=color, font=font)
        
        # Update the image
        image._imageData = img_copy

