"""
Display.py - Elevator display with Observer pattern
Implements SOLID: Single Responsibility (display rendering only)
                  Dependency Inversion (receives data from elevator)
"""

from typing import Optional
from Direction import ElevatorState, Direction


class Display:
    """
    Display unit showing elevator status to passengers.
    
    Design Pattern: Observer
    - Receives updates from ElevatorCar when state changes
    - Displays current floor, direction, and state
    
    SOLID Principles:
    - Single Responsibility: Only manages display output
    - Interface Segregation: Implements update(car) interface
    - Open/Closed: Can extend with new display formats
    """

    def __init__(self, display_id: int = 0):
        """
        Initialize display.
        
        Args:
            display_id: Unique identifier for this display
        """
        self.display_id = display_id
        self.current_floor = 0
        self.current_direction = Direction.IDLE
        self.current_state = ElevatorState.IDLE
        self.destination_floor: Optional[int] = None
        self.load_percentage = 0

    def update(self, car) -> None:
        """
        Update display based on elevator car state.
        
        This method is called by ElevatorCar when its state changes.
        Implements observer pattern.
        
        Args:
            car: ElevatorCar object with current state
        """
        self.current_floor = car.get_current_floor()
        self.current_direction = car.get_direction()
        self.current_state = car.get_state()
        self.destination_floor = car.get_next_destination()
        self.load_percentage = car.get_load_percentage()

    def render(self) -> str:
        """
        Render display output.
        
        Returns:
            String representation of display
        """
        state_symbol = self._get_state_symbol()
        direction_symbol = self._get_direction_symbol()

        return (
            f"┌─── Display #{self.display_id} ─────────┐\n"
            f"│ Floor: {self.current_floor:2d}              │\n"
            f"│ Direction: {direction_symbol}              │\n"
            f"│ State: {state_symbol:10s}        │\n"
            f"│ Load: {self.load_percentage:3d}%             │\n"
            f"│ Destination: {self.destination_floor if self.destination_floor else '-':2} │\n"
            f"└────────────────────────┘"
        )

    def get_floor(self) -> int:
        """Get displayed floor."""
        return self.current_floor

    def get_direction(self) -> Direction:
        """Get displayed direction."""
        return self.current_direction

    def get_state(self) -> ElevatorState:
        """Get displayed state."""
        return self.current_state

    def _get_state_symbol(self) -> str:
        """Get symbol representing current state."""
        state_map = {
            ElevatorState.IDLE: "⊗",
            ElevatorState.MOVING_UP: "↑",
            ElevatorState.MOVING_DOWN: "↓",
            ElevatorState.DOOR_OPEN: "⊙",
            ElevatorState.MAINTENANCE: "⚙",
            ElevatorState.EMERGENCY: "⚠",
        }
        return state_map.get(self.current_state, "?")

    def _get_direction_symbol(self) -> str:
        """Get symbol representing current direction."""
        direction_map = {
            Direction.UP: "↑",
            Direction.DOWN: "↓",
            Direction.IDLE: "-",
        }
        return direction_map.get(self.current_direction, "?")

    def __str__(self) -> str:
        return (
            f"Display(floor={self.current_floor}, "
            f"dir={self.current_direction}, "
            f"state={self.current_state})"
        )


class VerboseDisplay(Display):
    """
    Extended display with detailed information logging.
    
    Demonstrates SOLID Open/Closed principle - extends Display without modification.
    """

    def __init__(self, display_id: int = 0):
        super().__init__(display_id)
        self.log_history = []

    def update(self, car) -> None:
        """Update with logging."""
        old_floor = self.current_floor
        super().update(car)
        
        if old_floor != self.current_floor:
            log_entry = (
                f"[Display #{self.display_id}] "
                f"Floor changed: {old_floor} → {self.current_floor}"
            )
            self.log_history.append(log_entry)

    def render(self) -> str:
        """Render with additional details."""
        base_render = super().render()
        
        if self.log_history:
            recent_logs = "\n".join(self.log_history[-3:])  # Last 3 logs
            return base_render + "\n" + recent_logs
        
        return base_render

    def get_log_history(self) -> list:
        """Get complete log history."""
        return self.log_history.copy()


class MinimalDisplay(Display):
    """
    Minimal display showing only essential information.
    
    Use case: Hallway displays in building
    """

    def render(self) -> str:
        """Render minimal display."""
        direction = self._get_direction_symbol()
        return f"🛗 Floor: {self.current_floor} {direction}"