import logging
import yaml

from utils.landmarks_manager import LandmarkManager
from utils.optimizer import Optimizer
from utils.refiner import Refiner
from structs.landmark import Landmark
from structs.linked_landmarks import LinkedLandmarks
from structs.preferences import Preferences, Preference


logger = logging.getLogger(__name__)



def test(start_coords: tuple[float, float], finish_coords: tuple[float, float] = None) -> list[Landmark]:
    manager = LandmarkManager()
    optimizer = Optimizer()
    refiner = Refiner(optimizer=optimizer)

    
    preferences = Preferences(
        sightseeing=Preference(type='sightseeing', score = 5),
        nature=Preference(type='nature', score = 5),
        shopping=Preference(type='shopping', score = 5),
        max_time_minute=100,
        detour_tolerance_minute=0
    )

    # Create start and finish 
    if finish_coords is None :
        finish_coords = start_coords
    start = Landmark(name='start', type='start', location=start_coords, osm_type='', osm_id=0, attractiveness=0, n_tags = 0)
    finish = Landmark(name='finish', type='finish', location=finish_coords, osm_type='', osm_id=0, attractiveness=0, n_tags = 0)
    #finish = Landmark(name='finish', type=LandmarkType(landmark_type='finish'), location=(48.8777055, 2.3640967), osm_type='finish', osm_id=0, attractiveness=0, must_do=True, n_tags = 0)
    #start = Landmark(name='start', type=LandmarkType(landmark_type='start'), location=(48.847132, 2.312359), osm_type='start', osm_id=0, attractiveness=0, must_do=True, n_tags = 0)
    #finish = Landmark(name='finish', type=LandmarkType(landmark_type='finish'), location=(48.843185, 2.344533), osm_type='finish', osm_id=0, attractiveness=0, must_do=True, n_tags = 0)
    #finish = Landmark(name='finish', type=LandmarkType(landmark_type='finish'), location=(48.847132, 2.312359), osm_type='finish', osm_id=0, attractiveness=0, must_do=True, n_tags = 0)
    


    # Generate the landmarks from the start location
    landmarks, landmarks_short = manager.generate_landmarks_list(
        center_coordinates = start_coords,
        preferences = preferences
    )
    
    # Store data to file for debug purposes
    # write_data(landmarks, "landmarks_Strasbourg.txt")

    # Insert start and finish to the landmarks list
    landmarks_short.insert(0, start)
    landmarks_short.append(finish)

    # First stage optimization
    base_tour = optimizer.solve_optimization(max_time=preferences.max_time_minute, landmarks=landmarks_short)

    # Second stage using linear optimization
    refined_tour = refiner.refine_optimization(all_landmarks=landmarks, base_tour=base_tour, max_time = preferences.max_time_minute, detour = preferences.detour_tolerance_minute)

    linked_tour = LinkedLandmarks(refined_tour)
    total_time = 0           
    logger.info("Optimized route : ")
    for l in linked_tour :
        logger.info(f"{l}")
    logger.info(f"Estimated length of tour : {linked_tour.total_time} mintutes and visiting {len(linked_tour._landmarks)} landmarks.")

    # with open('linked_tour.yaml', 'w') as f:
    #     yaml.dump(linked_tour.asdict(), f)

    return linked_tour


# test(tuple((48.8344400, 2.3220540)))       # Café Chez César 
# test(tuple((48.8375946, 2.2949904)))       # Point random
# test(tuple((47.377859, 8.540585)))         # Zurich HB
# test(tuple((45.758217, 4.831814)))      # Lyon Bellecour
test(tuple((48.5848435, 7.7332974)))      # Strasbourg Gare
# test(tuple((48.2067858, 16.3692340)))      # Vienne
