"""Linked and ordered list of Landmarks that represents the visiting order."""

from .landmark import Landmark
from ..utils.get_time_distance import get_time

class LinkedLandmarks:
    """
    A list of landmarks that are linked together, e.g. in a route.
    Each landmark serves as a node in the linked list, but since we expect
    these to be consumed through the rest API, a pythonic reference to the next
    landmark is not well suited. Instead we use the uuid of the next landmark
    to reference the next landmark in the list. This is not very efficient,
    but appropriate for the expected use case
    ("short" trips with onyl few landmarks).
    """

    _landmarks = list[Landmark]
    total_time: int = 0

    def __init__(self, data: list[Landmark] = None) -> None:
        """
        Initialize a new LinkedLandmarks object. This expects an ORDERED list of landmarks,
        where the first landmark is the starting point and the last landmark is the end point.

        Args:
            data (list[Landmark], optional):    The list of landmarks that are linked together.
                                                Defaults to None.
        """
        self._landmarks = data if data else []
        self._link_landmarks()


    def _link_landmarks(self) -> None:
        """
        Create the links between the landmarks in the list by setting their 
        .next_uuid and the .time_to_next attributes.
        """

        # Mark secondary landmarks as such
        self.update_secondary_landmarks()


        for i, landmark in enumerate(self._landmarks[:-1]):
            landmark.next_uuid = self._landmarks[i + 1].uuid
            time_to_next = get_time(landmark.location, self._landmarks[i + 1].location)
            landmark.time_to_reach_next = time_to_next
            self.total_time += time_to_next
            self.total_time += landmark.duration

        self._landmarks[-1].next_uuid = None
        self._landmarks[-1].time_to_reach_next = 0

    def update_secondary_landmarks(self) -> None:
        """
        Mark landmarks with lower importance as secondary.
        """
        # Extract the attractiveness scores and sort them in descending order
        scores = sorted([landmark.attractiveness for landmark in self._landmarks], reverse=True)

        # Determine the 10th highest score
        if len(scores) >= 10:
            threshold_score = scores[9]
        else:
            # If there are fewer than 10 landmarks, use the lowest score as the threshold
            threshold_score = min(scores) if scores else 0

        # Update 'is_secondary' for landmarks with attractiveness below the threshold score
        for landmark in self._landmarks:
            if (landmark.attractiveness < threshold_score and landmark.type not in ["start", "finish"]):
                landmark.is_secondary = True


    def __getitem__(self, index: int) -> Landmark:
        return self._landmarks[index]


    def __str__(self) -> str:
        return f"LinkedLandmarks [{' ->'.join([str(landmark) for landmark in self._landmarks])}]"
