"""
Highlight operations coordination.

This module coordinates highlight operations with the highlight manager.
"""

from __future__ import annotations
from typing import List, Tuple, Optional, TYPE_CHECKING
from PIL import Image
import numpy as np

from pyWebLayout.core.highlight import Highlight, HighlightManager, HighlightColor, create_highlight_from_query_result

if TYPE_CHECKING:
    from pyWebLayout.layout.ereader_manager import EreaderLayoutManager


class HighlightCoordinator:
    """
    Coordinates highlight operations.

    This class provides a simplified interface for highlighting operations,
    coordinating between the layout manager and highlight manager.
    """

    def __init__(self, document_id: str, highlights_dir: str):
        """
        Initialize the highlight coordinator.

        Args:
            document_id: Unique document identifier
            highlights_dir: Directory to store highlights
        """
        self.highlight_manager = HighlightManager(
            document_id=document_id,
            highlights_dir=highlights_dir
        )
        self.layout_manager: Optional['EreaderLayoutManager'] = None

    def set_layout_manager(self, manager: 'EreaderLayoutManager'):
        """Set the layout manager."""
        self.layout_manager = manager

    def highlight_word(self, x: int, y: int,
                      color: Tuple[int, int, int, int] = None,
                      note: Optional[str] = None,
                      tags: Optional[List[str]] = None) -> Optional[str]:
        """
        Highlight a word at the given pixel location.

        Args:
            x: X coordinate
            y: Y coordinate
            color: RGBA color tuple (defaults to yellow)
            note: Optional annotation for this highlight
            tags: Optional categorization tags

        Returns:
            Highlight ID if successful, None otherwise
        """
        if not self.layout_manager:
            return None

        try:
            # Query the pixel to find the word
            page = self.layout_manager.get_current_page()
            result = page.query_point((x, y))
            if not result or not result.text:
                return None

            # Use default color if not provided
            if color is None:
                color = HighlightColor.YELLOW.value

            # Create highlight from query result
            highlight = create_highlight_from_query_result(
                result,
                color=color,
                note=note,
                tags=tags
            )

            # Add to manager
            self.highlight_manager.add_highlight(highlight)

            return highlight.id
        except Exception as e:
            print(f"Error highlighting word: {e}")
            return None

    def highlight_selection(self, start: Tuple[int, int], end: Tuple[int, int],
                           color: Tuple[int, int, int, int] = None,
                           note: Optional[str] = None,
                           tags: Optional[List[str]] = None) -> Optional[str]:
        """
        Highlight a range of words between two points.

        Args:
            start: Starting (x, y) coordinates
            end: Ending (x, y) coordinates
            color: RGBA color tuple (defaults to yellow)
            note: Optional annotation
            tags: Optional categorization tags

        Returns:
            Highlight ID if successful, None otherwise
        """
        if not self.layout_manager:
            return None

        try:
            page = self.layout_manager.get_current_page()
            selection_range = page.query_range(start, end)

            if not selection_range.results:
                return None

            # Use default color if not provided
            if color is None:
                color = HighlightColor.YELLOW.value

            # Create highlight from selection range
            highlight = create_highlight_from_query_result(
                selection_range,
                color=color,
                note=note,
                tags=tags
            )

            # Add to manager
            self.highlight_manager.add_highlight(highlight)

            return highlight.id
        except Exception as e:
            print(f"Error highlighting selection: {e}")
            return None

    def remove_highlight(self, highlight_id: str) -> bool:
        """Remove a highlight by ID."""
        return self.highlight_manager.remove_highlight(highlight_id)

    def list_highlights(self) -> List[Highlight]:
        """Get all highlights for the current document."""
        return self.highlight_manager.list_highlights()

    def get_highlights_for_page(self, page_bounds: Tuple[int, int, int, int]) -> List[Highlight]:
        """Get highlights that appear on a specific page."""
        return self.highlight_manager.get_highlights_for_page(page_bounds)

    def clear_all(self) -> None:
        """Remove all highlights from the current document."""
        self.highlight_manager.clear_all()

    def render_highlights(self, image: Image.Image, highlights: List[Highlight]) -> Image.Image:
        """
        Render highlight overlays on an image using multiply blend mode.

        Args:
            image: Base PIL Image to draw on
            highlights: List of Highlight objects to render

        Returns:
            New PIL Image with highlights overlaid
        """
        # Convert to RGB for processing
        original_mode = image.mode
        if image.mode == 'RGBA':
            rgb_image = image.convert('RGB')
            alpha_channel = image.split()[-1]
        else:
            rgb_image = image.convert('RGB')
            alpha_channel = None

        # Convert to numpy array for efficient processing
        img_array = np.array(rgb_image, dtype=np.float32)

        # Process each highlight
        for highlight in highlights:
            # Extract RGB components from highlight color (ignore alpha)
            h_r, h_g, h_b = highlight.color[0], highlight.color[1], highlight.color[2]

            # Create highlight multiplier (normalize to 0-1 range)
            highlight_color = np.array([h_r / 255.0, h_g / 255.0, h_b / 255.0], dtype=np.float32)

            for hx, hy, hw, hh in highlight.bounds:
                # Ensure bounds are within image
                hx, hy = max(0, hx), max(0, hy)
                x2, y2 = min(rgb_image.width, hx + hw), min(rgb_image.height, hy + hh)

                if x2 <= hx or y2 <= hy:
                    continue

                # Extract the region to highlight
                region = img_array[hy:y2, hx:x2, :]

                # Multiply with highlight color (like a real highlighter)
                highlighted = region * highlight_color

                # Put the highlighted region back
                img_array[hy:y2, hx:x2, :] = highlighted

        # Convert back to uint8 and create PIL Image
        img_array = np.clip(img_array, 0, 255).astype(np.uint8)
        result = Image.fromarray(img_array, mode='RGB')

        # Restore alpha channel if original had one
        if alpha_channel is not None and original_mode == 'RGBA':
            result = result.convert('RGBA')
            result.putalpha(alpha_channel)

        return result
