from __future__ import annotations

from typing import Optional, TYPE_CHECKING
from .elevator_logic_base import ElevatorLogic

if TYPE_CHECKING:
    from ..elevator import Elevator
    from ..floor import Floor

class FirstComeFirstServedLogic(ElevatorLogic):

    def __repr__(self) -> str:
        return "FirstComeFirstServedLogic"

    def assign_elevator_targets(self) -> None:
        # For each elevator, update its target based on FCFS logic
        for elevator in self.building.elevators:
            # If elevator is at target or has no target, find next target
            if elevator.state == 'IDLE' and (elevator.target_floor is None or
                                             elevator.target_floor == elevator.current_floor):
                next_target = self._get_next_target_fcfs(elevator)
                if next_target and next_target != elevator.current_floor:
                    elevator.target_floor = next_target
                elif not next_target and not elevator.onboard_passengers:
                    # No more targets and no passengers, clear target
                    elevator.target_floor = None

    def _get_next_target_fcfs(self, elevator: Elevator) -> Optional[Floor]:
        # First priority: serve onboard passengers (first passenger who boarded)
        if elevator.onboard_passengers:
            first_passenger = min(elevator.onboard_passengers, key=lambda p: p.tick_embarked or float('inf'))
            destination_floor = first_passenger.destination_floor
            if destination_floor and destination_floor != elevator.current_floor:
                return destination_floor

        # Second priority: pick up waiting passengers (if elevator has capacity)
        if not elevator.is_at_capacity():
            # Find the earliest waiting passenger across all floors
            earliest_tick = float('inf')
            earliest_floor = None

            for floor in self.building.floors:
                if floor.waiting_passengers:
                    # Get the earliest passenger on this floor
                    for passenger in floor.waiting_passengers:
                        if passenger.tick_appeared < earliest_tick:
                            earliest_tick = passenger.tick_appeared
                            earliest_floor = floor

            if earliest_floor and earliest_floor != elevator.current_floor:
                return earliest_floor

        return None
