# FlightMonitor/gui/panels/log_status_panel.py
"""
Panel for displaying application status (semaphore and message) and logs.
"""
import tkinter as tk
from tkinter import ttk
from tkinter.scrolledtext import ScrolledText
from tkinter import font as tkFont  # For checking font availability
from typing import Dict, Any, Optional

from flightmonitor.utils.logger import get_logger
from flightmonitor.utils.gui_utils import GUI_STATUS_UNKNOWN, SEMAPHORE_COLOR_STATUS_MAP

module_logger = get_logger(__name__)

# Constants for semaphore appearance
SEMAPHORE_SIZE = 12
SEMAPHORE_PAD = 3
SEMAPHORE_BORDER_WIDTH = 1
SEMAPHORE_TOTAL_SIZE = SEMAPHORE_SIZE + 2 * (SEMAPHORE_PAD + SEMAPHORE_BORDER_WIDTH)


class LogStatusPanel:
    """
    Manages the GUI elements for status display (semaphore, message) and logging.
    """

    def __init__(self, parent_frame: ttk.Frame, root_tk_instance: tk.Tk):
        """
        Initializes the LogStatusPanel.

        Args:
            parent_frame: The parent ttk.Frame where this panel will be placed.
            root_tk_instance: The main Tkinter root window instance.
        """
        self.parent_frame = parent_frame
        self.root_tk = root_tk_instance  # Needed for background color
        self._semaphore_oval_id: Optional[int] = None

        # --- Status Bar (Semaphore and Message) ---
        # Le righe seguenti creano il frame per la barra di stato, il canvas del semaforo
        # e l'etichetta del messaggio di stato. Questa è la prima parte della UI gestita da questo panel.
        self.status_bar_frame = ttk.Frame(self.parent_frame, padding=(5, 3))
        self.status_bar_frame.pack(side=tk.TOP, fill=tk.X, pady=(0, 5))

        self.semaphore_canvas = tk.Canvas(
            self.status_bar_frame,
            width=SEMAPHORE_TOTAL_SIZE,
            height=SEMAPHORE_TOTAL_SIZE,
            bg=self.root_tk.cget("bg"),  # Match root background
            highlightthickness=0,
        )
        self.semaphore_canvas.pack(side=tk.LEFT, padx=(0, 5))
        self._create_semaphore_oval() # Chiama il metodo helper per creare il cerchio del semaforo

        self.status_label = ttk.Label(
            self.status_bar_frame, text="Status: Initializing..."
        )
        self.status_label.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=(0, 2))

        # --- Log Area ---
        # Le righe seguenti creano il frame per l'area di log e il widget di testo scrollabile.
        # Questa è la seconda parte della UI gestita da questo panel.
        self.log_frame = ttk.Frame(self.parent_frame, padding=(5, 0, 5, 5))
        self.log_frame.pack(side=tk.TOP, fill=tk.BOTH, expand=True, padx=0, pady=0)

        # Determina il font per il widget di log. Preferisce "Consolas" se disponibile, altrimenti "Courier New".
        log_font_family = (
            "Consolas" if "Consolas" in tkFont.families() else "Courier New"
        )
        self.log_text_widget = ScrolledText(
            self.log_frame,
            state=tk.DISABLED, # Inizialmente disabilitato per prevenire input diretto dell'utente
            height=10,  # Altezza di default, la dimensione finale sarà gestita dalla PanedWindow
            wrap=tk.WORD, # Va a capo le parole
            font=(log_font_family, 9),
            relief=tk.SUNKEN, # Effetto visivo "incassato"
            borderwidth=1,
        )
        self.log_text_widget.pack(fill=tk.BOTH, expand=True, padx=0, pady=0)

        module_logger.debug("LogStatusPanel initialized.")

    def _create_semaphore_oval(self):
        """
        Private helper method to create the oval shape for the status semaphore.
        Called during initialization of the panel.
        """
        # Verifica che il canvas esista e che non sia già stato creato l'ID del semaforo per evitare errori.
        if not (
            self.semaphore_canvas
            and self.semaphore_canvas.winfo_exists()
            and hasattr(self, "_semaphore_oval_id")
        ):
            module_logger.warning(
                "Semaphore canvas not ready or attribute missing, cannot create oval."
            )
            return

        # Calcola le coordinate per il cerchio del semaforo, includendo padding e bordo.
        x0 = SEMAPHORE_PAD + SEMAPHORE_BORDER_WIDTH
        y0 = SEMAPHORE_PAD + SEMAPHORE_BORDER_WIDTH
        x1 = x0 + SEMAPHORE_SIZE
        y1 = y0 + SEMAPHORE_SIZE

        # Ottiene il colore iniziale dal dizionario di mappatura degli stati o un colore di default.
        initial_color = SEMAPHORE_COLOR_STATUS_MAP.get(
            GUI_STATUS_UNKNOWN, "gray70"
        )
        try:
            # Crea l'elemento ovale sul canvas e ne memorizza l'ID.
            self._semaphore_oval_id = self.semaphore_canvas.create_oval(
                x0,
                y0,
                x1,
                y1,
                fill=initial_color,
                outline="gray30",
                width=SEMAPHORE_BORDER_WIDTH,
            )
        except tk.TclError as e:
            # Logga un errore se la creazione fallisce (es. widget già distrutto).
            module_logger.error(f"Error creating semaphore oval: {e}")

    def update_status_display(self, status_level: str, message: str):
        """
        Updates the semaphore color and status message displayed in the GUI.

        Args:
            status_level: The new status level (e.g., GUI_STATUS_OK, GUI_STATUS_ERROR).
                          Used to determine the semaphore color.
            message: The new status message string to display next to the semaphore.
        """
        # Ottiene il colore corrispondente al livello di stato. Se non trovato, usa un colore di default.
        color_to_set = SEMAPHORE_COLOR_STATUS_MAP.get(
            status_level, SEMAPHORE_COLOR_STATUS_MAP.get(GUI_STATUS_UNKNOWN, "gray60")
        )

        # Aggiorna il colore del semaforo sul canvas, se il canvas esiste.
        if (
            self.semaphore_canvas
            and self.semaphore_canvas.winfo_exists()
            and self._semaphore_oval_id is not None
        ):
            try:
                self.semaphore_canvas.itemconfig(
                    self._semaphore_oval_id, fill=color_to_set
                )
            except tk.TclError:  # Cattura TclError che può accadere durante la chiusura dell'app
                pass

        # Aggiorna il testo dell'etichetta di stato, se l'etichetta esiste.
        current_status_text = f"Status: {message}"
        if self.status_label and self.status_label.winfo_exists():
            try:
                self.status_label.config(text=current_status_text)
            except tk.TclError:  # Cattura TclError che può accadere durante la chiusura dell'app
                pass

    def get_log_widget(self) -> ScrolledText:
        """
        Returns the Tkinter ScrolledText widget used for displaying logs.
        This method is essential as it allows the external logger setup
        (from `FlightMonitor.utils.logger`) to attach itself to this specific widget.

        Returns:
            The `tkinter.scrolledtext.ScrolledText` widget.
        """
        return self.log_text_widget