#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
Image Processor
图像处理器 - 重构版本，提供图像处理、变换和效果功能
"""

import logging
from typing import Tuple, List, Dict, Any, Optional, Union
from pathlib import Path
import colorsys
import math
from PIL import Image, ImageDraw, ImageFont, ImageFilter, ImageEnhance

logger = logging.getLogger(__name__)


class ImageProcessor:
    """图像处理工具类 - 重构版本"""
    
    def __init__(self):
        self.logger = logging.getLogger(__name__)
    
    def resize_image(
        self, 
        image: Image.Image, 
        target_size: Tuple[int, int], 
        keep_aspect: bool = True, 
        crop: bool = False
    ) -> Image.Image:
        """
        调整图像大小
        
        Args:
            image: 原始图像
            target_size: 目标尺寸 (宽, 高)
            keep_aspect: 是否保持宽高比
            crop: 是否裁剪以适应目标尺寸
            
        Returns:
            调整后的图像
        """
        if not keep_aspect:
            return image.resize(target_size, Image.LANCZOS)
        
        # 保持宽高比
        target_width, target_height = target_size
        width, height = image.size
        
        # 计算缩放比例
        ratio_w = target_width / width
        ratio_h = target_height / height
        
        if crop:
            # 裁剪模式：选择较大的比例以填满目标尺寸
            ratio = max(ratio_w, ratio_h)
            new_width = int(width * ratio)
            new_height = int(height * ratio)
            
            # 缩放图像
            resized = image.resize((new_width, new_height), Image.LANCZOS)
            
            # 计算裁剪位置（居中裁剪）
            left = (new_width - target_width) // 2
            top = (new_height - target_height) // 2
            right = left + target_width
            bottom = top + target_height
            
            return resized.crop((left, top, right, bottom))
        else:
            # 适应模式：选择较小的比例以完全显示图像
            ratio = min(ratio_w, ratio_h)
            new_width = int(width * ratio)
            new_height = int(height * ratio)
            
            # 缩放图像
            resized = image.resize((new_width, new_height), Image.LANCZOS)
            
            # 创建目标尺寸的画布并居中放置图像
            canvas = Image.new("RGBA", target_size, (0, 0, 0, 0))
            paste_x = (target_width - new_width) // 2
            paste_y = (target_height - new_height) // 2
            canvas.paste(resized, (paste_x, paste_y))
            
            return canvas

    def resize_and_crop(self, image: Image.Image, target_size: Tuple[int, int]) -> Image.Image:
        """调整大小并裁剪图像以适应目标尺寸"""
        return self.resize_image(image, target_size, keep_aspect=True, crop=True)

    def load_image(self, image_path: Union[str, Path]) -> Optional[Image.Image]:
        """
        加载图像文件
        
        Args:
            image_path: 图像文件路径
            
        Returns:
            PIL图像对象，失败时返回None
        """
        try:
            path = Path(image_path)
            if not path.exists():
                self.logger.error(f"图像文件不存在: {path}")
                return None
                
            image = Image.open(path)
            return image.convert("RGB")
            
        except Exception as e:
            self.logger.error(f"加载图像失败 {image_path}: {e}")
            return None

    def apply_blur(self, image: Image.Image, radius: float = 2.0) -> Image.Image:
        """应用模糊效果"""
        return image.filter(ImageFilter.GaussianBlur(radius=radius))

    def apply_brightness(self, image: Image.Image, factor: float = 1.0) -> Image.Image:
        """调整亮度"""
        enhancer = ImageEnhance.Brightness(image)
        return enhancer.enhance(factor)

    def apply_contrast(self, image: Image.Image, factor: float = 1.0) -> Image.Image:
        """调整对比度"""
        enhancer = ImageEnhance.Contrast(image)
        return enhancer.enhance(factor)

    def apply_saturation(self, image: Image.Image, factor: float = 1.0) -> Image.Image:
        """调整饱和度"""
        enhancer = ImageEnhance.Color(image)
        return enhancer.enhance(factor)

    def create_rounded_mask(self, size: Tuple[int, int], radius: int) -> Image.Image:
        """
        创建圆角遮罩
        
        Args:
            size: 遮罩尺寸
            radius: 圆角半径
            
        Returns:
            圆角遮罩图像
        """
        mask = Image.new("L", size, 0)
        draw = ImageDraw.Draw(mask)
        
        # 绘制圆角矩形
        draw.rounded_rectangle((0, 0, size[0], size[1]), radius=radius, fill=255)
        
        return mask

    def apply_rounded_corners(self, image: Image.Image, radius: int) -> Image.Image:
        """应用圆角效果"""
        mask = self.create_rounded_mask(image.size, radius)
        
        # 创建带透明通道的图像
        rounded = Image.new("RGBA", image.size, (0, 0, 0, 0))
        rounded.paste(image.convert("RGBA"), (0, 0))
        rounded.putalpha(mask)
        
        return rounded

    def create_shadow(
        self, 
        image: Image.Image, 
        offset: Tuple[int, int] = (5, 5),
        blur_radius: int = 10,
        shadow_color: Tuple[int, int, int, int] = (0, 0, 0, 128)
    ) -> Image.Image:
        """
        为图像添加阴影效果
        
        Args:
            image: 源图像
            offset: 阴影偏移 (x, y)
            blur_radius: 模糊半径
            shadow_color: 阴影颜色 (R, G, B, A)
            
        Returns:
            带阴影的图像
        """
        # 计算画布大小（需要容纳阴影）
        shadow_width = image.width + abs(offset[0]) + blur_radius * 2
        shadow_height = image.height + abs(offset[1]) + blur_radius * 2
        
        # 创建阴影画布
        shadow_canvas = Image.new("RGBA", (shadow_width, shadow_height), (0, 0, 0, 0))
        
        # 创建阴影形状
        shadow_shape = Image.new("RGBA", image.size, shadow_color)
        
        # 计算阴影位置
        shadow_x = max(0, offset[0]) + blur_radius
        shadow_y = max(0, offset[1]) + blur_radius
        
        # 贴上阴影并模糊
        shadow_canvas.paste(shadow_shape, (shadow_x, shadow_y))
        shadow_canvas = shadow_canvas.filter(ImageFilter.GaussianBlur(radius=blur_radius))
        
        # 计算原图位置
        image_x = max(0, -offset[0]) + blur_radius
        image_y = max(0, -offset[1]) + blur_radius
        
        # 贴上原图
        shadow_canvas.paste(image, (image_x, image_y), image if image.mode == "RGBA" else None)
        
        return shadow_canvas

    def extract_dominant_colors(self, image: Image.Image, num_colors: int = 5) -> List[Tuple[int, int, int]]:
        """
        提取图像主要颜色
        
        Args:
            image: 源图像
            num_colors: 提取颜色数量
            
        Returns:
            颜色列表 [(R, G, B), ...]
        """
        try:
            # 缩小图像以提高处理速度
            small_image = image.resize((150, 150))
            
            # 转换为RGB模式
            if small_image.mode != "RGB":
                small_image = small_image.convert("RGB")
            
            # 使用PIL的quantize方法提取主要颜色
            quantized = small_image.quantize(colors=num_colors)
            palette = quantized.getpalette()
            
            # 获取颜色统计
            colors = []
            for i in range(num_colors):
                r = palette[i * 3]
                g = palette[i * 3 + 1]
                b = palette[i * 3 + 2]
                colors.append((r, g, b))
            
            return colors
            
        except Exception as e:
            self.logger.error(f"提取主要颜色失败: {e}")
            return [(128, 128, 128)]  # 返回灰色作为默认值

    def adjust_color_harmony(
        self, 
        colors: List[Tuple[int, int, int]]
    ) -> List[Tuple[int, int, int]]:
        """
        调整颜色和谐度
        
        Args:
            colors: 原始颜色列表
            
        Returns:
            调整后的颜色列表
        """
        if not colors:
            return colors
        
        harmonized_colors = []
        
        for color in colors:
            r, g, b = color
            
            # 转换为HSV以便调整
            h, s, v = colorsys.rgb_to_hsv(r/255, g/255, b/255)
            
            # 调整饱和度和明度以增强和谐感
            s = min(1.0, max(0.3, s * 0.8))  # 降低饱和度
            v = min(1.0, max(0.2, v * 1.1))  # 稍微提高明度
            
            # 转换回RGB
            new_r, new_g, new_b = colorsys.hsv_to_rgb(h, s, v)
            harmonized_colors.append((
                int(new_r * 255),
                int(new_g * 255),
                int(new_b * 255)
            ))
        
        return harmonized_colors

    def create_gradient_overlay(
        self,
        size: Tuple[int, int],
        start_color: Tuple[int, int, int, int],
        end_color: Tuple[int, int, int, int],
        direction: str = "vertical"
    ) -> Image.Image:
        """
        创建渐变覆盖层
        
        Args:
            size: 覆盖层尺寸
            start_color: 起始颜色 (R, G, B, A)
            end_color: 结束颜色 (R, G, B, A)
            direction: 渐变方向
            
        Returns:
            渐变覆盖层图像
        """
        overlay = Image.new("RGBA", size, (0, 0, 0, 0))
        draw = ImageDraw.Draw(overlay)
        
        r1, g1, b1, a1 = start_color
        r2, g2, b2, a2 = end_color
        
        if direction == "vertical":
            for i in range(size[1]):
                ratio = i / size[1]
                r = int(r1 * (1 - ratio) + r2 * ratio)
                g = int(g1 * (1 - ratio) + g2 * ratio)
                b = int(b1 * (1 - ratio) + b2 * ratio)
                a = int(a1 * (1 - ratio) + a2 * ratio)
                draw.line([(0, i), (size[0], i)], fill=(r, g, b, a))
        else:  # horizontal
            for i in range(size[0]):
                ratio = i / size[0]
                r = int(r1 * (1 - ratio) + r2 * ratio)
                g = int(g1 * (1 - ratio) + g2 * ratio)
                b = int(b1 * (1 - ratio) + b2 * ratio)
                a = int(a1 * (1 - ratio) + a2 * ratio)
                draw.line([(i, 0), (i, size[1])], fill=(r, g, b, a))
        
        return overlay

    def apply_glass_effect(
        self,
        image: Image.Image,
        region: Tuple[int, int, int, int],  # (left, top, right, bottom)
        blur_radius: int = 15,
        opacity: int = 180
    ) -> Image.Image:
        """
        应用毛玻璃效果
        
        Args:
            image: 源图像
            region: 效果区域
            blur_radius: 模糊半径
            opacity: 不透明度
            
        Returns:
            应用效果后的图像
        """
        result = image.copy()
        
        # 提取指定区域
        left, top, right, bottom = region
        region_img = image.crop(region)
        
        # 应用模糊
        blurred = region_img.filter(ImageFilter.GaussianBlur(radius=blur_radius))
        
        # 创建半透明覆盖层
        overlay = Image.new("RGBA", region_img.size, (255, 255, 255, opacity))
        
        # 混合模糊图像和覆盖层
        glass_effect = Image.alpha_composite(
            blurred.convert("RGBA"),
            overlay
        )
        
        # 将效果应用回原图
        result.paste(glass_effect, (left, top))
        
        return result 