"""
Settings and rendering configuration management.

This module handles font size, spacing, and other rendering settings.
"""

from __future__ import annotations
from typing import Dict, Any, Optional
from PIL import Image

from pyWebLayout.layout.ereader_manager import EreaderLayoutManager


class SettingsManager:
    """
    Manages font size, spacing, and rendering settings.

    Responsibilities:
    - Font scale adjustment
    - Line spacing control
    - Inter-block spacing control
    - Word spacing control
    - Settings persistence helpers
    """

    def __init__(self):
        """Initialize the settings manager."""
        self.font_scale = 1.0
        self.font_scale_step = 0.1  # 10% change per step
        self.manager: Optional[EreaderLayoutManager] = None

    def set_manager(self, manager: EreaderLayoutManager):
        """
        Set the layout manager to control.

        Args:
            manager: EreaderLayoutManager instance to manage settings for
        """
        self.manager = manager
        self.font_scale = manager.font_scale

    def set_font_size(self, scale: float) -> Optional[Image.Image]:
        """
        Set the font size scale and re-render current page.

        Args:
            scale: Font scale factor (1.0 = normal, 2.0 = double size, 0.5 = half size)

        Returns:
            Rendered page with new font size, or None if no manager
        """
        if not self.manager:
            return None

        try:
            self.font_scale = max(0.5, min(3.0, scale))  # Clamp between 0.5x and 3.0x
            page = self.manager.set_font_scale(self.font_scale)
            return page.render() if page else None
        except Exception as e:
            print(f"Error setting font size: {e}")
            return None

    def increase_font_size(self) -> Optional[Image.Image]:
        """
        Increase font size by one step and re-render.

        Returns:
            Rendered page with increased font size
        """
        new_scale = self.font_scale + self.font_scale_step
        return self.set_font_size(new_scale)

    def decrease_font_size(self) -> Optional[Image.Image]:
        """
        Decrease font size by one step and re-render.

        Returns:
            Rendered page with decreased font size
        """
        new_scale = self.font_scale - self.font_scale_step
        return self.set_font_size(new_scale)

    def get_font_size(self) -> float:
        """
        Get the current font size scale.

        Returns:
            Current font scale factor
        """
        return self.font_scale

    def set_line_spacing(self, spacing: int) -> Optional[Image.Image]:
        """
        Set line spacing using pyWebLayout's native support.

        Args:
            spacing: Line spacing in pixels

        Returns:
            Rendered page with new line spacing
        """
        if not self.manager:
            return None

        try:
            # Calculate delta from current spacing
            current_spacing = self.manager.page_style.line_spacing
            target_spacing = max(0, spacing)
            delta = target_spacing - current_spacing

            # Use pyWebLayout's built-in methods to adjust spacing
            if delta > 0:
                self.manager.increase_line_spacing(abs(delta))
            elif delta < 0:
                self.manager.decrease_line_spacing(abs(delta))

            # Get re-rendered page
            page = self.manager.get_current_page()
            return page.render() if page else None
        except Exception as e:
            print(f"Error setting line spacing: {e}")
            return None

    def set_inter_block_spacing(self, spacing: int) -> Optional[Image.Image]:
        """
        Set inter-block spacing using pyWebLayout's native support.

        Args:
            spacing: Inter-block spacing in pixels

        Returns:
            Rendered page with new inter-block spacing
        """
        if not self.manager:
            return None

        try:
            # Calculate delta from current spacing
            current_spacing = self.manager.page_style.inter_block_spacing
            target_spacing = max(0, spacing)
            delta = target_spacing - current_spacing

            # Use pyWebLayout's built-in methods to adjust spacing
            if delta > 0:
                self.manager.increase_inter_block_spacing(abs(delta))
            elif delta < 0:
                self.manager.decrease_inter_block_spacing(abs(delta))

            # Get re-rendered page
            page = self.manager.get_current_page()
            return page.render() if page else None
        except Exception as e:
            print(f"Error setting inter-block spacing: {e}")
            return None

    def set_word_spacing(self, spacing: int) -> Optional[Image.Image]:
        """
        Set word spacing using pyWebLayout's native support.

        Args:
            spacing: Word spacing in pixels

        Returns:
            Rendered page with new word spacing
        """
        if not self.manager:
            return None

        try:
            # Calculate delta from current spacing
            current_spacing = self.manager.page_style.word_spacing
            target_spacing = max(0, spacing)
            delta = target_spacing - current_spacing

            # Use pyWebLayout's built-in methods to adjust spacing
            if delta > 0:
                self.manager.increase_word_spacing(abs(delta))
            elif delta < 0:
                self.manager.decrease_word_spacing(abs(delta))

            # Get re-rendered page
            page = self.manager.get_current_page()
            return page.render() if page else None
        except Exception as e:
            print(f"Error setting word spacing: {e}")
            return None

    def get_current_settings(self) -> Dict[str, Any]:
        """
        Get current rendering settings.

        Returns:
            Dictionary with all current settings
        """
        if not self.manager:
            return {
                'font_scale': self.font_scale,
                'line_spacing': 5,
                'inter_block_spacing': 15,
                'word_spacing': 0
            }

        return {
            'font_scale': self.font_scale,
            'line_spacing': self.manager.page_style.line_spacing,
            'inter_block_spacing': self.manager.page_style.inter_block_spacing,
            'word_spacing': self.manager.page_style.word_spacing
        }

    def apply_settings(self, settings: Dict[str, Any]) -> bool:
        """
        Apply rendering settings from a settings dictionary.

        This should be called after loading a book to restore user preferences.

        Args:
            settings: Dictionary with settings (font_scale, line_spacing, etc.)

        Returns:
            True if settings applied successfully, False otherwise
        """
        if not self.manager:
            return False

        try:
            # Apply font scale
            font_scale = settings.get('font_scale', 1.0)
            if font_scale != self.font_scale:
                self.set_font_size(font_scale)

            # Apply line spacing
            line_spacing = settings.get('line_spacing', 5)
            if line_spacing != self.manager.page_style.line_spacing:
                self.set_line_spacing(line_spacing)

            # Apply inter-block spacing
            inter_block_spacing = settings.get('inter_block_spacing', 15)
            if inter_block_spacing != self.manager.page_style.inter_block_spacing:
                self.set_inter_block_spacing(inter_block_spacing)

            # Apply word spacing
            word_spacing = settings.get('word_spacing', 0)
            if word_spacing != self.manager.page_style.word_spacing:
                self.set_word_spacing(word_spacing)

            return True

        except Exception as e:
            print(f"Error applying settings: {e}")
            return False
