# FlightMonitor/gui/main_window.py
"""
Main window of the Flight Monitor application.
Handles the layout with multiple notebooks for functions and views,
user interactions, status display including a semaphore, and logging.
"""
import tkinter as tk
from tkinter import ttk, messagebox, filedialog, Menu
from typing import List, Dict, Optional, Any, Tuple

from flightmonitor.data import config as app_config
from flightmonitor.utils.logger import get_logger, add_tkinter_handler, shutdown_logging_system
from flightmonitor.data.logging_config import LOGGING_CONFIG
from flightmonitor.utils.gui_utils import GUI_STATUS_OK, GUI_STATUS_WARNING, GUI_STATUS_ERROR, GUI_STATUS_FETCHING

from flightmonitor.gui.panels.log_status_panel import LogStatusPanel
from flightmonitor.gui.panels.map_tools_panel import MapToolsPanel
from flightmonitor.gui.panels.map_info_panel import MapInfoPanel
from flightmonitor.gui.panels.selected_flight_details_panel import SelectedFlightDetailsPanel
from flightmonitor.gui.panels.views_notebook_panel import ViewsNotebookPanel
from flightmonitor.gui.panels.function_notebook_panel import FunctionNotebookPanel, DEFAULT_PROFILE_NAME

try:
    from flightmonitor.map.map_canvas_manager import MapCanvasManager
    MAP_CANVAS_MANAGER_AVAILABLE = True
except ImportError as e_map_import:
    MapCanvasManager = None
    MAP_CANVAS_MANAGER_AVAILABLE = False
    print(f"CRITICAL ERROR in MainWindow: Failed to import MapCanvasManager: {e_map_import}.", flush=True)

try:
    from flightmonitor.gui.dialogs.import_progress_dialog import ImportProgressDialog
    IMPORT_DIALOG_AVAILABLE = True
except ImportError as e_dialog_import:
    ImportProgressDialog = None
    IMPORT_DIALOG_AVAILABLE = False
    print(f"ERROR in MainWindow: Failed to import ImportProgressDialog: {e_dialog_import}.", flush=True)

module_logger = get_logger(__name__)

class MainWindow:
    def __init__(self, root: tk.Tk, controller: Any):
        self.root = root
        self.controller = controller
        self.root.title("Flight Monitor")
        
        # --- Instance variables ---
        self.progress_dialog: Optional[ImportProgressDialog] = None
        self.full_flight_details_window: Optional[tk.Toplevel] = None
        self.map_manager_instance: Optional[MapCanvasManager] = None
        
        if app_config.LAYOUT_START_MAXIMIZED:
            try:
                self.root.state("zoomed")
            except tk.TclError:
                pass
        self.root.minsize(
            app_config.LAYOUT_WINDOW_MIN_WIDTH,
            app_config.LAYOUT_WINDOW_MIN_HEIGHT
        )

        self._create_menu()
        self._create_main_layout()
        self._create_panels()
        
        if self.log_status_panel.get_log_widget() and self.root:
            add_tkinter_handler(
                gui_log_widget=self.log_status_panel.get_log_widget(),
                root_tk_instance_for_gui_handler=self.root,
                logging_config_dict=LOGGING_CONFIG,
            )
        else:
            module_logger.error("LogStatusPanel or root not available for logger setup.")

        self.root.protocol("WM_DELETE_WINDOW", self._on_closing)
        self.root.after(100, self._delayed_initialization)
        module_logger.info("MainWindow basic structure initialized.")

    def _create_menu(self):
        menubar = Menu(self.root)
        file_menu = Menu(menubar, tearoff=0)
        file_menu.add_command(
            label="Import Aircraft Database (CSV)...",
            command=self._import_aircraft_db_csv,
        )
        file_menu.add_separator()
        file_menu.add_command(label="Exit", command=self._on_closing)
        menubar.add_cascade(label="File", menu=file_menu)
        self.root.config(menu=menubar)

    def _create_main_layout(self):
        main_hpane = ttk.PanedWindow(self.root, orient=tk.HORIZONTAL)
        main_hpane.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
        
        left_column_frame = ttk.Frame(main_hpane)
        main_hpane.add(left_column_frame, weight=app_config.LAYOUT_MAIN_HORIZONTAL_WEIGHTS["left_column"])
        
        right_column_frame = ttk.Frame(main_hpane)
        main_hpane.add(right_column_frame, weight=app_config.LAYOUT_MAIN_HORIZONTAL_WEIGHTS["right_column"])

        left_vpane = ttk.PanedWindow(left_column_frame, orient=tk.VERTICAL)
        left_vpane.pack(fill=tk.BOTH, expand=True)

        self.function_and_area_frame = ttk.Frame(left_vpane)
        left_vpane.add(self.function_and_area_frame, weight=app_config.LAYOUT_LEFT_VERTICAL_WEIGHTS["function_notebook"])

        self.log_status_area_frame_container = ttk.Frame(left_vpane)
        left_vpane.add(self.log_status_area_frame_container, weight=app_config.LAYOUT_LEFT_VERTICAL_WEIGHTS["log_status_area"])

        right_vpane = ttk.PanedWindow(right_column_frame, orient=tk.VERTICAL)
        right_vpane.pack(fill=tk.BOTH, expand=True)
        self.views_notebook_outer_frame = ttk.Frame(right_vpane)
        right_vpane.add(self.views_notebook_outer_frame, weight=app_config.LAYOUT_RIGHT_VERTICAL_WEIGHTS["views_notebook"])
        self.map_tools_info_area_frame = ttk.Frame(right_vpane)
        right_vpane.add(self.map_tools_info_area_frame, weight=app_config.LAYOUT_RIGHT_VERTICAL_WEIGHTS["map_tools_info"])

    def _create_panels(self):
        self.function_notebook_panel = FunctionNotebookPanel(self.function_and_area_frame, self.controller)
        self.log_status_panel = LogStatusPanel(self.log_status_area_frame_container, self.root)
        
        self.views_notebook_panel = ViewsNotebookPanel(self.views_notebook_outer_frame)
        
        bottom_panel_container = ttk.Frame(self.map_tools_info_area_frame)
        bottom_panel_container.pack(fill=tk.BOTH, expand=True)
        bottom_weights = app_config.LAYOUT_BOTTOM_PANELS_HORIZONTAL_WEIGHTS
        bottom_panel_container.columnconfigure(0, weight=bottom_weights.get("map_tools", 1))
        bottom_panel_container.columnconfigure(1, weight=bottom_weights.get("map_info", 2))
        bottom_panel_container.columnconfigure(2, weight=bottom_weights.get("flight_details", 2))

        map_tool_frame = ttk.LabelFrame(bottom_panel_container, text="Map Tools", padding=5)
        map_tool_frame.grid(row=0, column=0, sticky="nsew", padx=(0, 2))
        self.map_tools_panel = MapToolsPanel(map_tool_frame, self.controller)

        map_info_panel_frame = ttk.LabelFrame(bottom_panel_container, text="Map Information", padding=10)
        map_info_panel_frame.grid(row=0, column=1, sticky="nsew", padx=2)
        self.map_info_panel = MapInfoPanel(map_info_panel_frame)

        selected_flight_details_frame = ttk.LabelFrame(bottom_panel_container, text="Selected Flight Details", padding=10)
        selected_flight_details_frame.grid(row=0, column=2, sticky="nsew", padx=(2, 0))
        self.selected_flight_details_panel = SelectedFlightDetailsPanel(selected_flight_details_frame, self.controller)

    def get_bounding_box_from_gui(self) -> Optional[Dict[str, float]]:
        return self.function_notebook_panel.get_bounding_box_input()

    def update_bbox_gui_fields(self, bbox_dict: Dict[str, float]):
        self.function_notebook_panel.update_bbox_gui_fields(bbox_dict)
        
    def set_monitoring_button_states(self, is_monitoring_active: bool):
        self.function_notebook_panel.set_monitoring_button_states(is_monitoring_active)
        self.function_notebook_panel.set_controls_state(not is_monitoring_active)

    def update_semaphore_and_status(self, status_level: str, message: str):
        self.log_status_panel.update_status_display(status_level, message)
        
    def _reset_gui_to_stopped_state(self, status_message: Optional[str] = "Monitoring stopped."):
        self.set_monitoring_button_states(False)
        status_level = GUI_STATUS_ERROR if "error" in status_message.lower() else GUI_STATUS_OK
        self.update_semaphore_and_status(status_level, status_message)

    def _on_closing(self):
        if messagebox.askokcancel("Quit", "Do you want to quit Flight Monitor?", parent=self.root):
            if self.controller: self.controller.on_application_exit()
            shutdown_logging_system()
            if self.root: self.root.destroy()
                
    def _import_aircraft_db_csv(self):
        if not (self.controller and hasattr(self.controller, "import_aircraft_database_from_file_with_progress")):
            self.show_error_message("Controller Error", "Import function not available.")
            return

        filepath = filedialog.askopenfilename(
            master=self.root, title="Select Aircraft Database CSV File",
            filetypes=(("CSV files", "*.csv"), ("All files", "*.*"))
        )
        if filepath:
            if IMPORT_DIALOG_AVAILABLE and ImportProgressDialog:
                if self.progress_dialog and self.progress_dialog.winfo_exists():
                    self.progress_dialog.destroy()
                self.progress_dialog = ImportProgressDialog(self.root, file_name=filepath)
                self.controller.import_aircraft_database_from_file_with_progress(
                    filepath, self.progress_dialog
                )
            else:
                self.show_info_message("Import Started", "Importing in background. Check logs for completion.")
    
    def show_error_message(self, title: str, message: str):
        if self.root.winfo_exists():
            messagebox.showerror(title, message, parent=self.root)

    def show_info_message(self, title: str, message: str):
        if self.root.winfo_exists():
            messagebox.showinfo(title, message, parent=self.root)

    def update_selected_flight_details(self, flight_data: Optional[Dict[str, Any]]):
        self.selected_flight_details_panel.update_details(flight_data)

    def clear_all_views_data(self):
        module_logger.info("GUI: Clearing all views data.")
        if self.map_manager_instance:
            self.map_manager_instance.clear_map_display()
        else:
            self._update_map_placeholder("Map Cleared. Ready.")
        self.selected_flight_details_panel.update_details(None)
        
    def _delayed_initialization(self):
        if not self.root.winfo_exists(): return

        if MAP_CANVAS_MANAGER_AVAILABLE:
            initial_bbox = self.get_bounding_box_from_gui()
            self.root.after(200, self._initialize_map_manager, initial_bbox)
        else:
            self._update_map_placeholder("Map functionality disabled (Import Error).")

        # MODIFICA: Invochiamo il caricamento del profilo di default da qui,
        # dopo che la mappa è stata programmata per l'inizializzazione.
        self.root.after(250, lambda: self.controller.load_area_profile(DEFAULT_PROFILE_NAME))
        
        self.function_notebook_panel._on_tab_change()
        module_logger.info("MainWindow fully initialized.")

    def _initialize_map_manager(self, initial_bbox_for_map: Optional[Dict[str, float]]):
        flight_canvas = self.views_notebook_panel.get_map_canvas()
        if not (flight_canvas and flight_canvas.winfo_exists()):
            return

        canvas_w, canvas_h = flight_canvas.winfo_width(), flight_canvas.winfo_height()
        if canvas_w > 1 and canvas_h > 1:
            try:
                self.map_manager_instance = MapCanvasManager(
                    app_controller=self.controller,
                    tk_canvas=flight_canvas,
                    initial_bbox_dict=initial_bbox_for_map,
                )
                if hasattr(self.controller, "update_general_map_info"):
                    self.controller.update_general_map_info()
            except Exception as e_init:
                module_logger.critical(f"Failed to initialize MapCanvasManager: {e_init}", exc_info=True)
                self.show_error_message("Map Error", f"Could not initialize map: {e_init}")
                self._update_map_placeholder(f"Map Error:\n{e_init}")
        else:
            self.root.after(300, self._initialize_map_manager, initial_bbox_for_map)

    def _update_map_placeholder(self, text_to_display: str):
        flight_canvas = self.views_notebook_panel.get_map_canvas()
        if not (flight_canvas and flight_canvas.winfo_exists()): return
        
        if self.map_manager_instance and not self.map_manager_instance.is_detail_map:
             flight_canvas.delete("placeholder_text")
             return

        try:
            flight_canvas.delete("placeholder_text")
            w, h = flight_canvas.winfo_width(), flight_canvas.winfo_height()
            flight_canvas.create_text(
                w / 2, h / 2, text=text_to_display, tags="placeholder_text",
                fill="gray50", font=("Arial", 12, "italic"), justify=tk.CENTER
            )
        except tk.TclError:
            pass

    def update_clicked_map_info(self, lat_deg, lon_deg, lat_dms, lon_dms):
        self.map_info_panel.update_clicked_map_info(lat_deg, lon_deg, lat_dms, lon_dms)

    def update_general_map_info_display(self, zoom, map_size_str, map_geo_bounds, target_bbox_input, flight_count):
        self.map_info_panel.update_general_map_info_display(zoom, map_size_str, map_geo_bounds, target_bbox_input, flight_count)

    def show_map_context_menu(self, latitude, longitude, screen_x, screen_y):
        if self.map_manager_instance:
            self.map_manager_instance.show_map_context_menu_from_gui(latitude, longitude, screen_x, screen_y)