"""
Text formatting strategies for text output.
Handles all text formatting and manipulation for output.
Follows the Strategy pattern and Single Responsibility Principle.
"""
from abc import ABC, abstractmethod
from typing import List, Optional


class TextFormattingStrategy(ABC):
    """Abstract base class for text formatting strategies."""
    
    @abstractmethod
    def format(self, *args, **kwargs) -> str:
        """Format text according to the specific strategy.
        
        Returns:
            The formatted text
        """
        pass


class QuantityFormattingStrategy(TextFormattingStrategy):
    """Formats quantity values with units."""
    
    def format(self, value, unit: Optional[str] = None) -> str:
        """Format a quantity value with its unit.
        
        Args:
            value: The quantity value
            unit: Optional unit string
            
        Returns:
            Formatted quantity string (e.g., "123.45 meters")
        """
        if value is None:
            return ""
        
        value_str = str(value).strip()
        if unit:
            unit_str = str(unit).strip()
            return f"{value_str} {unit_str}" if unit_str else value_str
        return value_str


class LocationFormattingStrategy(TextFormattingStrategy):
    """Formats location strings."""
    
    def format(self, caption: str, location: str) -> str:
        """Format a caption with its location.
        
        Args:
            caption: The main caption
            location: The location string
            
        Returns:
            Formatted string (e.g., "caption in location")
        """
        if not caption:
            return ""
        if not location:
            return caption
        return f"{caption} in {location}"


class ListJoiningStrategy(TextFormattingStrategy):
    """Joins multiple strings into a single formatted string."""
    
    def __init__(self, separator: str = ". "):
        """Initialize the joining strategy.
        
        Args:
            separator: The separator to use between items
        """
        self._separator = separator
    
    def format(self, items: List[str]) -> str:
        """Join multiple strings with a separator.
        
        Args:
            items: List of strings to join
            
        Returns:
            Joined string
        """
        if not items:
            return ""
        return self._separator.join(str(item) for item in items if item)


class SentenceJoiningStrategy(ListJoiningStrategy):
    """Joins multiple sentences with period and space."""
    
    def __init__(self):
        super().__init__(separator=". ")


class CommaJoiningStrategy(ListJoiningStrategy):
    """Joins multiple items with comma and space."""
    
    def __init__(self):
        super().__init__(separator=", ")


class TextFormatter:
    """
    Context class that uses a formatting strategy.
    Follows the Strategy pattern for flexible formatting behavior.
    """
    
    def __init__(self, strategy: TextFormattingStrategy):
        """Initialize the formatter with a specific strategy.
        
        Args:
            strategy: The formatting strategy to use
        """
        self._strategy = strategy
    
    def format(self, *args, **kwargs) -> str:
        """Format text using the configured strategy.
        
        Returns:
            The formatted text
        """
        return self._strategy.format(*args, **kwargs)
    
    def set_strategy(self, strategy: TextFormattingStrategy):
        """Change the formatting strategy.
        
        Args:
            strategy: The new formatting strategy to use
        """
        self._strategy = strategy


# Convenience functions for common formatting operations
def format_quantity(value, unit: Optional[str] = None) -> str:
    """
    Format a quantity value with its unit.
    
    Args:
        value: The quantity value
        unit: Optional unit string
        
    Returns:
        Formatted quantity string
    """
    strategy = QuantityFormattingStrategy()
    return strategy.format(value, unit)


def format_location(caption: str, location: str) -> str:
    """
    Format a caption with its location.
    
    Args:
        caption: The main caption
        location: The location string
        
    Returns:
        Formatted location string
    """
    strategy = LocationFormattingStrategy()
    return strategy.format(caption, location)


def join_sentences(sentences: List[str]) -> str:
    """
    Join multiple sentences with period and space.
    
    Args:
        sentences: List of sentences to join
        
    Returns:
        Joined sentence string
    """
    strategy = SentenceJoiningStrategy()
    return strategy.format(sentences)


def join_with_comma(items: List[str]) -> str:
    """
    Join multiple items with comma and space.
    
    Args:
        items: List of items to join
        
    Returns:
        Comma-separated string
    """
    strategy = CommaJoiningStrategy()
    return strategy.format(items)
