"""
Factory for creating interaction commands based on interaction type.

This implements the Strategy pattern, allowing different command builders
to be registered and used based on the interaction type.
"""

from typing import Optional, Dict, Any
from pyPhotoAlbum.models import BaseLayoutElement
from .interaction_command_builders import (
    CommandBuilder,
    MoveCommandBuilder,
    ResizeCommandBuilder,
    RotateCommandBuilder,
    ImagePanCommandBuilder,
)


class InteractionCommandFactory:
    """
    Factory for creating commands from interaction data.

    Uses the Strategy pattern to delegate command creation to
    specialized builder classes based on interaction type.
    """

    def __init__(self):
        """Initialize factory with default builders."""
        self._builders: Dict[str, CommandBuilder] = {}
        self._register_default_builders()

    def _register_default_builders(self):
        """Register the default command builders."""
        self.register_builder("move", MoveCommandBuilder())
        self.register_builder("resize", ResizeCommandBuilder())
        self.register_builder("rotate", RotateCommandBuilder())
        self.register_builder("image_pan", ImagePanCommandBuilder())

    def register_builder(self, interaction_type: str, builder: CommandBuilder):
        """
        Register a command builder for an interaction type.

        Args:
            interaction_type: The type of interaction (e.g., 'move', 'resize')
            builder: The CommandBuilder instance to handle this type
        """
        self._builders[interaction_type] = builder

    def create_command(
        self, interaction_type: str, element: BaseLayoutElement, start_state: dict, **kwargs
    ) -> Optional[Any]:
        """
        Create a command based on interaction type and state changes.

        Args:
            interaction_type: Type of interaction ('move', 'resize', etc.)
            element: The element that was interacted with
            start_state: Dictionary containing initial state values
            **kwargs: Additional context for command creation

        Returns:
            Command object if changes warrant it, None otherwise
        """
        builder = self._builders.get(interaction_type)

        if builder is None:
            print(f"Warning: No builder registered for interaction type '{interaction_type}'")
            return None

        if not builder.can_build(element, start_state, **kwargs):
            return None

        return builder.build(element, start_state, **kwargs)

    def has_builder(self, interaction_type: str) -> bool:
        """Check if a builder is registered for the given interaction type."""
        return interaction_type in self._builders

    def get_supported_types(self) -> list:
        """Get list of supported interaction types."""
        return list(self._builders.keys())


class InteractionState:
    """
    Value object representing the state of an interaction.

    This simplifies passing interaction data around and makes
    the code more maintainable.
    """

    def __init__(
        self,
        element: Optional[BaseLayoutElement] = None,
        interaction_type: Optional[str] = None,
        position: Optional[tuple] = None,
        size: Optional[tuple] = None,
        rotation: Optional[float] = None,
        crop_info: Optional[tuple] = None,
    ):
        """
        Initialize interaction state.

        Args:
            element: The element being interacted with
            interaction_type: Type of interaction
            position: Initial position
            size: Initial size
            rotation: Initial rotation
            crop_info: Initial crop info (for images)
        """
        self.element = element
        self.interaction_type = interaction_type
        self.position = position
        self.size = size
        self.rotation = rotation
        self.crop_info = crop_info

    def to_dict(self) -> dict:
        """
        Convert state to dictionary for command builders.

        Returns:
            Dict with non-None state values
        """
        state: Dict[str, Any] = {}
        if self.position is not None:
            state["position"] = self.position
        if self.size is not None:
            state["size"] = self.size
        if self.rotation is not None:
            state["rotation"] = self.rotation
        if self.crop_info is not None:
            state["crop_info"] = self.crop_info
        return state

    def is_valid(self) -> bool:
        """Check if state has required fields for command creation."""
        return self.element is not None and self.interaction_type is not None

    def clear(self):
        """Clear all state values."""
        self.element = None
        self.interaction_type = None
        self.position = None
        self.size = None
        self.rotation = None
        self.crop_info = None
