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 ShortestSeekTimeFirstLogic(ElevatorLogic):

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

    def assign_elevator_targets(self) -> None:
        # For each elevator, update its target based on SSTF 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_sstf(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

            # Even when moving, update target if a closer floor appears
            elif elevator.state in ['MOVING_UP', 'MOVING_DOWN']:
                next_target = self._get_next_target_sstf(elevator)
                if next_target and next_target != elevator.current_floor:
                    # Update to closer target (SSTF always picks shortest distance)
                    current_target_num = int(elevator.target_floor) if elevator.target_floor else float('inf')
                    next_target_num = int(next_target)
                    current_floor_num = int(elevator.current_floor)

                    # Calculate distances
                    current_target_distance = abs(current_floor_num - current_target_num)
                    next_target_distance = abs(current_floor_num - next_target_num)

                    # If needed, switch to closer target
                    if next_target_distance < current_target_distance:
                        elevator.target_floor = next_target

    def _get_next_target_sstf(self, elevator: Elevator) -> Optional[Floor]:
        current_floor_num = int(elevator.current_floor)

        closest_floor = None
        min_distance = float('inf')

        # Check onboard passenger destinations
        for passenger in elevator.onboard_passengers:
            if passenger.destination_floor:
                dest_floor_num = int(passenger.destination_floor)
                distance = abs(current_floor_num - dest_floor_num)
                if 0 < distance < min_distance:  # Exclude current floor
                    min_distance = distance
                    closest_floor = passenger.destination_floor

        # Check floors with waiting passengers (if elevator has capacity)
        if not elevator.is_at_capacity():
            for floor in self.building.floors:
                if floor.waiting_passengers:
                    floor_num = int(floor)
                    distance = abs(current_floor_num - floor_num)
                    if 0 < distance < min_distance:  # Exclude current floor
                        min_distance = distance
                        closest_floor = floor

        return closest_floor
