"""
Button.py - Button hierarchy implementing Command Pattern
Implements SOLID: Interface Segregation (each button type has specific behavior)
                  Liskov Substitution (all buttons can be executed)
"""

from abc import ABC, abstractmethod
from typing import Callable, Optional


class Button(ABC):
    """
    Abstract base class for all buttons in the elevator system.
    
    Design Pattern: Command Pattern
    - Each button press can be treated as an object that can be queued, executed, etc.
    
    SOLID Principles:
    - Interface Segregation: Minimal interface (execute, is_pressed)
    - Liskov Substitution: All button types substitute Button transparently
    - Open/Closed: Easy to add new button types without modifying existing code
    """

    def __init__(self, action: Optional[Callable] = None):
        """
        Initialize button with optional action callback.
        
        Args:
            action: Optional callable to execute when button is pressed
        """
        self._pressed = False
        self._action = action

    def press(self) -> None:
        """Mark button as pressed and execute associated action."""
        self._pressed = True
        self.execute()

    def release(self) -> None:
        """Mark button as released."""
        self._pressed = False

    def is_pressed(self) -> bool:
        """Check if button is currently pressed."""
        return self._pressed

    @abstractmethod
    def execute(self) -> None:
        """Execute the action associated with this button press."""
        if self._action:
            self._action()

    def __str__(self) -> str:
        return f"{self.__class__.__name__}(pressed={self._pressed})"


class HallButton(Button):
    """
    Button pressed by passenger on a floor to call an elevator.
    
    Attributes:
        floor: Which floor this button is on
        direction: UP or DOWN direction requested
    
    SOLID: Single Responsibility - only handles hall calls
    """

    def __init__(self, floor: int, direction, action: Optional[Callable] = None):
        """
        Initialize hall button.
        
        Args:
            floor: Floor number for this button
            direction: Direction enum (UP or DOWN)
            action: Callback when pressed (typically registered with system)
        """
        super().__init__(action)
        self.floor = floor
        self.direction = direction

    def execute(self) -> None:
        """Execute: notify system of hall call."""
        super().execute()

    def get_floor(self) -> int:
        """Get the floor number."""
        return self.floor

    def get_direction(self):
        """Get the direction (UP/DOWN)."""
        return self.direction

    def __str__(self) -> str:
        return f"HallButton(floor={self.floor}, dir={self.direction}, pressed={self._pressed})"


class ElevatorButton(Button):
    """
    Button pressed inside an elevator to select destination floor.
    
    Attributes:
        floor: Destination floor selected
    
    SOLID: Single Responsibility - only handles interior floor selection
    """

    def __init__(self, floor: int, action: Optional[Callable] = None):
        """
        Initialize elevator button (floor selector).
        
        Args:
            floor: Destination floor number
            action: Callback when pressed (typically registered with car)
        """
        super().__init__(action)
        self.floor = floor

    def execute(self) -> None:
        """Execute: register floor request with elevator car."""
        super().execute()

    def get_destination_floor(self) -> int:
        """Get the destination floor."""
        return self.floor

    def __str__(self) -> str:
        return f"ElevatorButton(floor={self.floor}, pressed={self._pressed})"


class DoorButton(Button):
    """
    Base class for door-related buttons (open/close).
    
    SOLID: Interface Segregation - minimal door control interface
    """

    def __init__(self, door_action: str, action: Optional[Callable] = None):
        """
        Initialize door button.
        
        Args:
            door_action: "OPEN" or "CLOSE"
            action: Callback when pressed
        """
        super().__init__(action)
        self.door_action = door_action

    def execute(self) -> None:
        """Execute: trigger door action."""
        super().execute()

    def get_action(self) -> str:
        """Get the door action type."""
        return self.door_action


class DoorOpenButton(DoorButton):
    """Button to open door manually."""

    def __init__(self, action: Optional[Callable] = None):
        super().__init__("OPEN", action)

    def __str__(self) -> str:
        return f"DoorOpenButton(pressed={self._pressed})"


class DoorCloseButton(DoorButton):
    """Button to close door manually."""

    def __init__(self, action: Optional[Callable] = None):
        super().__init__("CLOSE", action)

    def __str__(self) -> str:
        return f"DoorCloseButton(pressed={self._pressed})"


class EmergencyButton(Button):
    """
    Emergency stop button to halt elevator immediately.
    
    SOLID: Single Responsibility - only triggers emergency stop
    """

    def __init__(self, action: Optional[Callable] = None):
        """
        Initialize emergency button.
        
        Args:
            action: Callback when pressed (typically stops car immediately)
        """
        super().__init__(action)

    def execute(self) -> None:
        """Execute: trigger emergency stop."""
        super().execute()

    def __str__(self) -> str:
        return f"EmergencyButton(emergency_active={self._pressed})"


class AlarmButton(Button):
    """Button to sound alarm and alert maintenance staff."""

    def __init__(self, action: Optional[Callable] = None):
        super().__init__(action)

    def execute(self) -> None:
        """Execute: sound alarm."""
        super().execute()

    def __str__(self) -> str:
        return f"AlarmButton(alarm_active={self._pressed})"