# radar_data_reader/gui/main_window.py

"""
Main View for the Radar Data Reader application.
Features a tab for processing .out files and a tab for converting .rec files.
"""

import tkinter as tk
from tkinter import scrolledtext, ttk, messagebox
import logging
from typing import Dict, Any, List, Optional
import queue

from .gui_utils import center_window
from ..utils import logger
from ..core.export_profiles import ExportProfile
from .segment_processor_tab import SegmentProcessorTab

log = logger.get_logger(__name__)

try:
    from radar_data_reader import _version as wrapper_version

    WRAPPER_APP_VERSION_STRING = f"{wrapper_version.__version__} ({wrapper_version.GIT_BRANCH}/{wrapper_version.GIT_COMMIT_HASH[:7]})"
    WRAPPER_BUILD_INFO = f"Wrapper Built: {wrapper_version.BUILD_TIMESTAMP}"
except ImportError:
    WRAPPER_APP_VERSION_STRING = "(Dev Wrapper)"
    WRAPPER_BUILD_INFO = "Wrapper build time unknown"


class MainWindow(tk.Frame):
    """The main application window (View)."""

    def __init__(self, master: tk.Tk, controller, logging_config: Dict[str, Any]):
        super().__init__(master)
        self.master = master
        self.controller = controller

        self.gui_update_queue = controller.result_queue
        self.total_blocks_for_progress = 0
        self.profile_editor_window = None
        self.rec_config_window = None
        self.export_config_window = None
        self.segments_done_count = 0

        self._init_vars()
        self.pack(fill=tk.BOTH, expand=True)
        self.master.title(
            f"Radar Data Reader & Processor - {WRAPPER_APP_VERSION_STRING}"
        )
        self.master.geometry("1280x1024")

        self._create_widgets()
        self._setup_gui_logging(logging_config)

        self.master.protocol("WM_DELETE_WINDOW", self.on_close)
        log.info("Main window View initialized.")

    def _init_vars(self):
        """Initialize all Tkinter variables."""
        self.status_bar_var = tk.StringVar(value="Ready")

        # --- Variabili per "Single OUT Processor" ---
        self.out_filepath_var = tk.StringVar()
        self.out_output_dir_var = tk.StringVar()
        self.out_basename_var = tk.StringVar()
        self.out_output_csv_var = tk.BooleanVar(value=True)
        self.out_csv_use_tab_var = tk.BooleanVar(value=False)
        self.out_output_json_var = tk.BooleanVar(value=False)
        self.out_use_full_path_var = tk.BooleanVar(value=False)
        self.out_csv_profile_var = tk.StringVar()
        self.out_json_profile_var = tk.StringVar()
        self.out_analysis_only_var = tk.BooleanVar(value=False)
        self.out_debug_dump_var = tk.BooleanVar(value=False)

        # --- Variabili per "REC Converter" ---
        self.rec_filepath_var = tk.StringVar()
        self.rec_file_count_var = tk.IntVar(value=1)
        self.rec_output_dir_var = tk.StringVar()
        self.rec_basename_var = tk.StringVar()

        # --- Variabili per "Flight Analyzer" ---
        self.analyzer_rec_folder_var = tk.StringVar()
        self.analyzer_flight_name_var = tk.StringVar()
        self.analyzer_workspace_dir_var = tk.StringVar()
        self.analyzer_info_var = tk.StringVar(value="Please select a folder and a flight name.")
        self.aggregate_by_scale_var = tk.BooleanVar(value=True)
        self.aggregate_by_waveform_var = tk.BooleanVar(value=True)
        
        # --- MODIFICA: Variabili per la barra di progresso GLOBALE ---
        self.global_progress_text_var = tk.StringVar(value="N/A")
        self.global_progress_bar_var = tk.DoubleVar(value=0)
        self.global_batches_found_var = tk.StringVar(value="N/A")

    def _on_analysis_only_toggle(self):
        is_analysis_only = self.out_analysis_only_var.get()
        state = tk.DISABLED if is_analysis_only else tk.NORMAL
        
        self.out_csv_check.config(state=state)
        self.out_json_check.config(state=state)
        self.out_csv_profile_combobox.config(state=state)
        self.out_json_profile_combobox.config(state=state)
        
        if not is_analysis_only:
            if self.out_output_csv_var.get():
                self.out_csv_profile_combobox.config(state="readonly")
            if self.out_output_json_var.get():
                self.out_json_profile_combobox.config(state="readonly")

    def _create_widgets(self):
        menu_bar = tk.Menu(self.master)
        self.master.config(menu=menu_bar)
        file_menu = tk.Menu(menu_bar, tearoff=0)
        menu_bar.add_cascade(label="File", menu=file_menu)
        file_menu.add_command(
            label="Manage Export Profiles...",
            command=self.controller.open_profile_editor,
        )
        file_menu.add_separator()
        file_menu.add_command(label="Exit", command=self.on_close)

        main_frame = tk.Frame(self)
        main_frame.pack(padx=10, pady=10, fill=tk.BOTH, expand=True)
        main_frame.columnconfigure(0, weight=1)
        # --- MODIFICA: Aggiunta una riga per la progress bar globale ---
        main_frame.rowconfigure(2, weight=1) 

        self.notebook = ttk.Notebook(main_frame)
        self.notebook.grid(row=0, column=0, sticky="nsew", pady=(0, 10))

        # --- MODIFICA: Creazione e posizionamento del frame di progresso globale ---
        global_progress_frame = self._create_global_progress_frame(main_frame)
        global_progress_frame.grid(row=1, column=0, sticky="ew", pady=5)
        
        # --- MODIFICA: Posizionamento della console di log nella riga corretta ---
        self._create_log_console_frame(main_frame).grid(row=2, column=0, sticky="nsew", pady=(5, 0))

        # Creazione dei tab
        self.flight_analyzer_tab = ttk.Frame(self.notebook, padding="10")
        self.segment_processor_tab = SegmentProcessorTab(self.notebook, self.controller)
        self.out_processor_tab = ttk.Frame(self.notebook, padding="10")
        self.rec_converter_tab = ttk.Frame(self.notebook, padding="10")

        self.notebook.add(self.flight_analyzer_tab, text="1. Flight Analyzer")
        self.notebook.add(self.segment_processor_tab, text="2. Segment Processor")
        self.notebook.add(self.out_processor_tab, text="3. Single OUT Processor")
        self.notebook.add(self.rec_converter_tab, text="4. REC to OUT Converter")

        # Popolamento dei tab (ora senza le loro barre di progresso)
        self._create_flight_analyzer_tab(self.flight_analyzer_tab)
        self._create_out_processor_tab(self.out_processor_tab)
        self._create_rec_converter_tab(self.rec_converter_tab)
        
        self.status_bar = ttk.Label(
            self,
            textvariable=self.status_bar_var,
            relief=tk.SUNKEN,
            anchor=tk.W,
            padding=2,
        )
        self.status_bar.pack(side=tk.BOTTOM, fill=tk.X)

    def _create_global_progress_frame(self, parent):
        """Crea il pannello di stato e progresso globale."""
        frame = ttk.LabelFrame(parent, text="Global Process Status")
        frame.columnconfigure(1, weight=1)

        self.global_progress_bar = ttk.Progressbar(
            frame, variable=self.global_progress_bar_var, maximum=100
        )
        self.global_progress_bar.grid(
            row=0, column=0, columnspan=3, sticky="ew", padx=5, pady=(5, 2)
        )
        
        ttk.Label(frame, text="Status:", anchor="e").grid(
            row=1, column=0, padx=(10, 5), pady=2, sticky="w"
        )
        ttk.Label(frame, textvariable=self.global_progress_text_var, anchor="w").grid(
            row=1, column=1, padx=5, pady=2, sticky="ew"
        )
        
        batches_frame = ttk.Frame(frame)
        batches_frame.grid(row=1, column=2, sticky='e', padx=10)
        ttk.Label(batches_frame, text="Batches Found:", anchor="e").pack(side=tk.LEFT)
        ttk.Label(batches_frame, textvariable=self.global_batches_found_var, anchor="w").pack(side=tk.LEFT, padx=(5,0))
        
        return frame

    def _create_flight_analyzer_tab(self, parent):
        parent.columnconfigure(0, weight=1)
        # --- MODIFICA: Ora la row 4 è quella dei risultati, non più 5 ---
        parent.rowconfigure(4, weight=1)

        # --- Frame 1: Flight Source ---
        setup_frame = ttk.LabelFrame(parent, text="Flight Source")
        setup_frame.grid(row=0, column=0, sticky="ew", padx=5, pady=5)
        setup_frame.columnconfigure(1, weight=1)
        ttk.Label(setup_frame, text="Recordings Folder:").grid(row=0, column=0, padx=5, pady=5, sticky="w")
        rec_folder_entry = ttk.Entry(setup_frame, textvariable=self.analyzer_rec_folder_var, state="readonly")
        rec_folder_entry.grid(row=0, column=1, sticky="ew", padx=5)
        ttk.Button(setup_frame, text="Browse...", command=self.controller.select_and_analyze_flight_folder).grid(row=0, column=2, padx=5)

        # --- Frame 2: Workspace ---
        workspace_frame = ttk.LabelFrame(parent, text="Flight Workspace (Analysis Output)")
        workspace_frame.grid(row=1, column=0, sticky="ew", padx=5, pady=5)
        workspace_frame.columnconfigure(1, weight=1)
        ttk.Label(workspace_frame, text="Workspace Path:").grid(row=0, column=0, padx=5, pady=5, sticky="w")
        workspace_entry = ttk.Entry(workspace_frame, textvariable=self.analyzer_workspace_dir_var)
        workspace_entry.grid(row=0, column=1, sticky="ew", padx=5)
        dir_buttons_frame = ttk.Frame(workspace_frame)
        dir_buttons_frame.grid(row=0, column=2, padx=5)
        ttk.Button(
            dir_buttons_frame, text="Browse...", 
            command=lambda: self.controller.select_output_dir(self.analyzer_workspace_dir_var)
        ).pack(side=tk.LEFT)
        ttk.Button(
            dir_buttons_frame, text="Open...", 
            command=lambda: self.controller.open_folder_from_path(self.analyzer_workspace_dir_var.get())
        ).pack(side=tk.LEFT, padx=(5, 0))
        ttk.Label(workspace_frame, text="Flight Name:").grid(row=1, column=0, padx=5, pady=5, sticky="w")
        flight_name_entry = ttk.Entry(workspace_frame, textvariable=self.analyzer_flight_name_var)
        flight_name_entry.grid(row=1, column=1, columnspan=2, sticky="ew", padx=5)

        # --- Frame 3: Segment Definition ---
        aggregation_frame = ttk.LabelFrame(parent, text="Segment Definition Options")
        aggregation_frame.grid(row=2, column=0, sticky="ew", padx=5, pady=5)
        ttk.Checkbutton(
            aggregation_frame, 
            text="Create new segment on Scale change",
            variable=self.aggregate_by_scale_var
        ).pack(side=tk.LEFT, padx=10, pady=5)
        ttk.Checkbutton(
            aggregation_frame, 
            text="Create new segment on Waveform (WF) change",
            variable=self.aggregate_by_waveform_var
        ).pack(side=tk.LEFT, padx=10, pady=5)

        # --- Frame 4: Actions & Info ---
        action_frame = ttk.Frame(parent)
        action_frame.grid(row=3, column=0, sticky="ew", padx=5, pady=10)
        self.start_analysis_button = ttk.Button(action_frame, text="Start Flight Analysis", command=self.controller.start_flight_analysis, state=tk.DISABLED)
        self.start_analysis_button.pack(side=tk.LEFT, padx=(0, 5))
        self.open_flight_folder_button = ttk.Button(action_frame, text="Open Flight Folder", command=self.controller.open_current_flight_folder, state=tk.DISABLED)
        self.open_flight_folder_button.pack(side=tk.LEFT, padx=5)
        info_label = ttk.Label(action_frame, textvariable=self.analyzer_info_var)
        info_label.pack(side=tk.LEFT, padx=20)
        
        # --- RIMOZIONE: Frame di progresso locale rimosso ---

        # --- Frame 5 (ex 6): Results ---
        results_frame = ttk.LabelFrame(parent, text="Flight Summary & Segments")
        results_frame.grid(row=4, column=0, sticky="nsew", padx=5, pady=5) # Row index aggiornato
        results_frame.columnconfigure(0, weight=1)
        results_frame.rowconfigure(0, weight=1)
        self.flight_timeline_tree = ttk.Treeview(
            results_frame,
            columns=("status", "start_batch", "end_batch", "batch_count", "duration", "start_file", "end_file", "file_count"),
            show="headings", selectmode="extended"
        )
        # ... (configurazione treeview rimane invariata) ...
        self.flight_timeline_tree.heading("status", text="Segment (Mode | Scale | WF)")
        self.flight_timeline_tree.heading("start_batch", text="Start Batch")
        self.flight_timeline_tree.heading("end_batch", text="End Batch")
        self.flight_timeline_tree.heading("batch_count", text="Batch Count")
        self.flight_timeline_tree.heading("duration", text="Duration (s)")
        self.flight_timeline_tree.heading("start_file", text="Start File")
        self.flight_timeline_tree.heading("end_file", text="End File")
        self.flight_timeline_tree.heading("file_count", text="# Files")
        self.flight_timeline_tree.column("status", width=250, stretch=True)
        self.flight_timeline_tree.column("start_batch", width=90, anchor="center")
        self.flight_timeline_tree.column("end_batch", width=90, anchor="center")
        self.flight_timeline_tree.column("batch_count", width=90, anchor="center")
        self.flight_timeline_tree.column("duration", width=90, anchor="center")
        self.flight_timeline_tree.column("start_file", width=200, stretch=True)
        self.flight_timeline_tree.column("end_file", width=200, stretch=True)
        self.flight_timeline_tree.column("file_count", width=60, anchor="center")
        self.flight_timeline_tree.grid(row=0, column=0, sticky="nsew")
        tree_scrollbar = ttk.Scrollbar(results_frame, orient="vertical", command=self.flight_timeline_tree.yview)
        self.flight_timeline_tree.configure(yscrollcommand=tree_scrollbar.set)
        tree_scrollbar.grid(row=0, column=1, sticky="ns")
        buttons_frame = ttk.Frame(results_frame)
        buttons_frame.grid(row=1, column=0, columnspan=2, sticky="ew", pady=5)
        ttk.Button(buttons_frame, text="Select All", command=self._select_all_segments).pack(side=tk.LEFT, padx=(0, 5))
        ttk.Button(buttons_frame, text="Select None", command=self._deselect_all_segments).pack(side=tk.LEFT)
        self.export_segment_button = ttk.Button(buttons_frame, text="Export Selected Segment(s)", state=tk.DISABLED, command=self.controller.start_segment_export)
        self.export_segment_button.pack(side=tk.RIGHT)
        configure_export_button = ttk.Button(buttons_frame, text="Configure Segment Export...", command=self.controller.open_export_config_editor)
        configure_export_button.pack(side=tk.RIGHT, padx=5)

    def _select_all_segments(self):
        children = self.flight_timeline_tree.get_children()
        self.flight_timeline_tree.selection_set(children)

    def _deselect_all_segments(self):
        self.flight_timeline_tree.selection_remove(
            self.flight_timeline_tree.selection()
        )

    def _create_out_processor_tab(self, parent):
        parent.columnconfigure(1, weight=1)
        
        # ... (Input Frame, Output Frame, Formats & Options Frame rimangono invariati) ...
        # --- Input Frame ---
        input_frame = ttk.LabelFrame(parent, text="Input .out File")
        input_frame.grid(row=0, column=0, columnspan=3, sticky="ew", padx=5, pady=5)
        input_frame.columnconfigure(1, weight=1)
        ttk.Label(input_frame, text="File Path:").grid(
            row=0, column=0, padx=5, pady=5, sticky="w"
        )
        out_file_entry = ttk.Entry(
            input_frame, textvariable=self.out_filepath_var, state="readonly"
        )
        out_file_entry.grid(row=0, column=1, sticky="ew", padx=5)
        self.out_browse_button = ttk.Button(
            input_frame, text="Browse...", command=self.controller.select_out_file
        )
        self.out_browse_button.grid(row=0, column=2, padx=5, pady=5)
        self.out_filepath_var.trace_add("write", self.controller.on_out_config_changed)

        # --- Output Frame ---
        output_frame = ttk.LabelFrame(parent, text="Output Configuration")
        output_frame.grid(row=1, column=0, columnspan=3, sticky="ew", padx=5, pady=5)
        output_frame.columnconfigure(1, weight=1)
        ttk.Label(output_frame, text="Output Directory:").grid(
            row=0, column=0, padx=5, pady=5, sticky="w"
        )
        out_dir_entry = ttk.Entry(output_frame, textvariable=self.out_output_dir_var)
        out_dir_entry.grid(row=0, column=1, sticky="ew", padx=5)
        out_dir_buttons_frame = ttk.Frame(output_frame)
        out_dir_buttons_frame.grid(row=0, column=2, padx=5)
        ttk.Button(
            out_dir_buttons_frame,
            text="Browse...",
            command=lambda: self.controller.select_output_dir(self.out_output_dir_var),
        ).pack(side=tk.LEFT)
        ttk.Button(
            out_dir_buttons_frame,
            text="Open...",
            command=lambda: self.controller.open_folder_from_path(
                self.out_output_dir_var.get()
            ),
        ).pack(side=tk.LEFT, padx=(5, 0))
        ttk.Label(output_frame, text="Base Filename:").grid(
            row=1, column=0, padx=5, pady=5, sticky="w"
        )
        ttk.Entry(output_frame, textvariable=self.out_basename_var).grid(
            row=1, column=1, columnspan=2, sticky="ew", padx=5
        )

        # --- Formats & Options Frame ---
        formats_frame = ttk.LabelFrame(parent, text="Output Formats & Options")
        formats_frame.grid(row=2, column=0, columnspan=3, sticky="ew", padx=5, pady=5)
        formats_frame.columnconfigure(1, weight=1)
        analysis_check = ttk.Checkbutton(
            formats_frame,
            text="Generate Structure Analysis Report Only",
            variable=self.out_analysis_only_var,
            command=self._on_analysis_only_toggle
        )
        analysis_check.grid(row=0, column=0, columnspan=3, sticky="w", padx=5, pady=(5, 10))
        separator = ttk.Separator(formats_frame, orient='horizontal')
        separator.grid(row=1, column=0, columnspan=3, sticky='ew', padx=5, pady=5)
        self.out_csv_check = ttk.Checkbutton(
            formats_frame, text="Generate .csv file", variable=self.out_output_csv_var
        )
        self.out_csv_check.grid(row=2, column=0, sticky="w", padx=5, pady=2)
        self.out_csv_profile_combobox = ttk.Combobox(
            formats_frame,
            textvariable=self.out_csv_profile_var,
            state="readonly",
            width=25,
        )
        self.out_csv_profile_combobox.grid(row=2, column=1, sticky="w", padx=5)
        self.out_json_check = ttk.Checkbutton(
            formats_frame, text="Generate .json file", variable=self.out_output_json_var
        )
        self.out_json_check.grid(row=3, column=0, sticky="w", padx=5, pady=2)
        self.out_json_profile_combobox = ttk.Combobox(
            formats_frame,
            textvariable=self.out_json_profile_var,
            state="readonly",
            width=25,
        )
        self.out_json_profile_combobox.grid(row=3, column=1, sticky="w", padx=5)
        options_subframe = ttk.Frame(formats_frame)
        options_subframe.grid(row=2, column=2, rowspan=3, sticky="w", padx=(20, 5))
        ttk.Checkbutton(
            options_subframe,
            text="Use Tab Separator (CSV)",
            variable=self.out_csv_use_tab_var,
        ).pack(anchor="w")
        ttk.Checkbutton(
            options_subframe,
            text="Use Full Path for Headers",
            variable=self.out_use_full_path_var,
        ).pack(anchor="w")
        ttk.Checkbutton(
            options_subframe,
            text="Enable Structure Debug Dump",
            variable=self.out_debug_dump_var,
        ).pack(anchor="w", pady=(5,0))
        
        # --- Action & Live Data Frames ---
        action_frame = ttk.Frame(parent)
        action_frame.grid(row=3, column=0, columnspan=3, pady=(10, 0))
        self.out_process_button = ttk.Button(
            action_frame,
            text="Process .out File",
            command=self.controller.start_out_processing,
        )
        self.out_process_button.pack(side=tk.LEFT, padx=5)
        self.out_stop_button = ttk.Button(
            action_frame,
            text="Stop",
            command=self.controller.stop_processing,
            state=tk.DISABLED,
        )
        self.out_stop_button.pack(side=tk.LEFT, padx=5)
        
        # --- RIMOZIONE: Frame di progresso locale rimosso ---

    def _create_rec_converter_tab(self, parent):
        # ... (Questo tab non aveva una barra di progresso, quindi rimane invariato) ...
        parent.columnconfigure(1, weight=1)
        input_frame = ttk.LabelFrame(parent, text="Input REC Sequence")
        input_frame.grid(row=0, column=0, columnspan=3, sticky="ew", padx=5, pady=5)
        input_frame.columnconfigure(1, weight=1)
        ttk.Label(input_frame, text="First .rec File:").grid(
            row=0, column=0, padx=5, pady=5, sticky="w"
        )
        rec_file_entry = ttk.Entry(
            input_frame, textvariable=self.rec_filepath_var, state="readonly"
        )
        rec_file_entry.grid(row=0, column=1, sticky="ew", padx=5)
        ttk.Button(
            input_frame, text="Browse...", command=self.controller.select_rec_file
        ).grid(row=0, column=2, padx=5)
        ttk.Label(input_frame, text="Number of Files (/n):").grid(
            row=1, column=0, padx=5, pady=5, sticky="w"
        )
        ttk.Spinbox(
            input_frame,
            from_=1,
            to=1000,
            textvariable=self.rec_file_count_var,
            width=10,
        ).grid(row=1, column=1, padx=5, pady=5, sticky="w")
        self.rec_filepath_var.trace_add("write", self.controller.on_rec_config_changed)
        self.rec_file_count_var.trace_add(
            "write", self.controller.on_rec_config_changed
        )
        output_frame = ttk.LabelFrame(parent, text="Generated .out File")
        output_frame.grid(row=1, column=0, columnspan=3, sticky="ew", padx=5, pady=5)
        output_frame.columnconfigure(1, weight=1)
        ttk.Label(output_frame, text="Output Directory:").grid(
            row=0, column=0, padx=5, pady=5, sticky="w"
        )
        rec_dir_entry = ttk.Entry(output_frame, textvariable=self.rec_output_dir_var)
        rec_dir_entry.grid(row=0, column=1, sticky="ew", padx=5)
        rec_dir_buttons_frame = ttk.Frame(output_frame)
        rec_dir_buttons_frame.grid(row=0, column=2, padx=5)
        ttk.Button(
            rec_dir_buttons_frame,
            text="Browse...",
            command=lambda: self.controller.select_output_dir(self.rec_output_dir_var),
        ).pack(side=tk.LEFT)
        ttk.Button(
            rec_dir_buttons_frame,
            text="Open...",
            command=lambda: self.controller.open_folder_from_path(
                self.rec_output_dir_var.get()
            ),
        ).pack(side=tk.LEFT, padx=(5, 0))
        ttk.Label(output_frame, text="Generated Filename:").grid(
            row=1, column=0, padx=5, pady=5, sticky="w"
        )
        ttk.Label(
            output_frame,
            textvariable=self.rec_basename_var,
            relief="sunken",
            anchor="w",
        ).grid(row=1, column=1, columnspan=2, sticky="ew", padx=5)
        action_frame = ttk.Frame(parent)
        action_frame.grid(row=2, column=0, columnspan=3, pady=(10, 0))
        self.rec_convert_button = ttk.Button(
            action_frame,
            text="Convert REC to OUT",
            command=self.controller.start_rec_conversion,
        )
        self.rec_convert_button.pack(side=tk.LEFT, padx=5)
        self.rec_config_button = ttk.Button(
            action_frame,
            text="g_reconverter Advanced Config...",
            command=self.controller.open_rec_config_editor,
        )
        self.rec_config_button.pack(side=tk.LEFT, padx=5)
        self.process_generated_out_button = ttk.Button(
            action_frame,
            text="Process Generated .out File ->",
            command=self.controller.process_last_generated_out,
            state=tk.DISABLED,
        )
        self.process_generated_out_button.pack(side=tk.LEFT, padx=5)

    def _create_log_console_frame(self, parent):
        log_frame = ttk.LabelFrame(parent, text="Log Console")
        log_frame.rowconfigure(0, weight=1)
        log_frame.columnconfigure(0, weight=1)
        self.log_widget = scrolledtext.ScrolledText(
            log_frame, state=tk.DISABLED, wrap=tk.WORD, bg="#f0f0f0"
        )
        self.log_widget.grid(row=0, column=0, sticky="nsew", padx=5, pady=5)
        self.log_widget.tag_config("INFO", foreground="black")
        self.log_widget.tag_config("ERROR", foreground="red", font=("", 0, "bold"))
        self.log_widget.tag_config("SUCCESS", foreground="green")
        self.log_widget.tag_config("WARNING", foreground="orange")
        self.log_widget.tag_config("DEBUG", foreground="gray")
        self.log_widget.tag_config("CMD", foreground="blue")
        return log_frame

    def _setup_gui_logging(self, logging_config):
        logger.add_tkinter_handler(self.log_widget, self.master, logging_config)

    def update_export_profiles(self, profiles: List[ExportProfile], **kwargs):
        profile_names = [p.name for p in profiles] if profiles else []
        active_profile_name = kwargs.get("active_out_profile", "")

        self.out_csv_profile_combobox["values"] = profile_names
        self.out_json_profile_combobox["values"] = profile_names
        if active_profile_name in profile_names:
            self.out_csv_profile_var.set(active_profile_name)
            self.out_json_profile_var.set(active_profile_name)
        elif profile_names:
            self.out_csv_profile_var.set(profile_names[0])
            self.out_json_profile_var.set(profile_names[0])
        else:
            self.out_csv_profile_var.set("")
            self.out_json_profile_var.set("")

        self.segment_processor_tab.update_export_profiles(
            profile_names, active_profile_name
        )

    def _reset_progress(self):
        # --- MODIFICA: Resetta solo le variabili globali ---
        self.global_progress_bar_var.set(0)
        self.global_progress_text_var.set("N/A")
        self.global_batches_found_var.set("N/A")
        self.segments_done_count = 0

    def start_processing_ui(self):
        self.update_ui_for_processing_state(True)
        self._reset_progress()
        self.after(100, self.poll_result_queue)

    def update_ui_for_processing_state(self, is_processing: bool):
        state = tk.DISABLED if is_processing else tk.NORMAL

        self.out_browse_button.config(state=state)
        self.rec_convert_button.config(state=state)
        self.start_analysis_button.config(state=state)
        self.export_segment_button.config(state=state)

        if hasattr(self, "segment_processor_tab"):
            self.segment_processor_tab.load_segments_button.config(state=state)
            is_ready_for_batch = (
                self.segment_processor_tab.process_button["state"] != tk.DISABLED
            )
            self.segment_processor_tab.process_button.config(
                state=(
                    tk.NORMAL
                    if not is_processing and is_ready_for_batch
                    else tk.DISABLED
                )
            )

        self.out_stop_button.config(state=tk.NORMAL if is_processing else tk.DISABLED)

        if not is_processing:
            can_process_generated = (
                self.controller.last_generated_out_file
                and self.controller.last_generated_out_file.exists()
            )
            self.process_generated_out_button.config(
                state=tk.NORMAL if can_process_generated else tk.DISABLED
            )

            flight_folder = self.controller.flight_analyzer.current_flight_folder_path
            can_open_folder = flight_folder and flight_folder.exists()
            self.open_flight_folder_button.config(
                state=tk.NORMAL if can_open_folder else tk.DISABLED
            )
        else:
            self.process_generated_out_button.config(state=tk.DISABLED)
            self.open_flight_folder_button.config(state=tk.DISABLED)

        if is_processing:
            self.status_bar_var.set("Processing... Please wait.")
            self.master.config(cursor="watch")
        else:
            self.status_bar_var.set("Ready")
            self.master.config(cursor="")

    def update_rec_tab_buttons_state(self, conversion_successful: bool):
        self.process_generated_out_button.config(
            state=tk.NORMAL if conversion_successful else tk.DISABLED
        )

    def poll_result_queue(self):
        try:
            while not self.gui_update_queue.empty():
                msg = self.gui_update_queue.get_nowait()
                msg_type = msg.get("type")

                # ... (gestori per 'log', 'export_log' rimangono invariati) ...
                if msg_type == "log":
                    level_str = msg.get("level", "INFO").upper()
                    level_map = {"ERROR": logging.ERROR, "WARNING": logging.WARNING, "SUCCESS": logging.INFO, "DEBUG": logging.DEBUG}
                    log_level = level_map.get(level_str, logging.INFO)
                    log.log(log_level, f"[C++ Runner] {msg.get('message')}")
                elif msg_type == "export_log":
                    log.info(f"[C++ Export] {msg.get('message')}")
                
                elif msg_type == "start":
                    self.total_blocks_for_progress = msg.get("total", 0)
                    self.global_progress_bar_var.set(0)
                    self.global_progress_text_var.set("Starting...")
                
                # --- NUOVO GESTORE PER IL PROGRESSO DELL'ANALISI ---
                elif msg_type == "analysis_progress":
                    current = msg.get("current", 0)
                    total = msg.get("total", 0)
                    if total > 0:
                        progress = (current / total) * 100
                        self.global_progress_bar_var.set(progress)
                        self.global_progress_text_var.set(f"Analyzing file structure... ({current} / {total} blocks)")

                elif msg_type == "data_batch_fragment":
                    # ... (gestione frammenti rimane invariata) ...
                    blocks_done = msg.get("blocks_done", 0)
                    if self.total_blocks_for_progress > 0:
                        progress_percent = (blocks_done / self.total_blocks_for_progress) * 100
                        self.global_progress_bar_var.set(progress_percent)
                    self.global_progress_text_var.set(f"Processing .out file... ({blocks_done} / {self.total_blocks_for_progress} blocks)")
                    self.controller.handle_data_batch_fragment(msg.get("data"))
                    self.global_batches_found_var.set(f"{self.controller.total_batches_found_count}")

                elif msg_type == "analysis_report":
                    self.global_progress_bar_var.set(100)
                    self.global_progress_text_var.set("Analysis complete. Saving report...")
                    self.controller.handle_analysis_report(msg)

                # ... (tutti gli altri gestori di messaggi rimangono invariati) ...
                elif msg_type == "file_progress":
                    file_num, total_files = msg.get("file_number", 0), self.controller.total_files_for_analysis
                    if total_files > 0:
                        self.global_progress_bar_var.set((file_num / total_files) * 100)
                        self.global_progress_text_var.set(f"Analyzing flight file {file_num} / {total_files}")
                
                elif msg_type == "segment_progress":
                    self.segments_done_count += 1
                    total_segs = self.controller.total_segments_for_export
                    if total_segs > 0:
                        self.global_progress_bar_var.set((self.segments_done_count / total_segs) * 100)
                        self.global_progress_text_var.set(f"Exporting segment {self.segments_done_count} / {total_segs}")
                
                elif msg_type == "batch_progress":
                    current, total = msg.get("current", 0), msg.get("total", 0)
                    if total > 0:
                        self.global_progress_bar_var.set((current / total) * 100)
                        self.global_progress_text_var.set(f"Batch processing segment {current} of {total}: {msg.get('segment_name', '')}")
                
                elif msg_type == "cpp_complete":
                    self.global_progress_text_var.set("C++ analysis finished. Parsing results...")
                    self.controller.handle_final_analysis_steps()
                
                elif msg_type == "analysis_summary_data":
                    self.controller.handle_analysis_summary_data(msg)
                
                elif msg_type in ("success", "complete", "error"):
                    self.global_progress_bar_var.set(100)
                    self.global_progress_text_var.set("Finished.")
                    self.controller.handle_worker_completion(msg)

        except queue.Empty:
            pass
        except Exception as e:
            log.error(f"Error in GUI polling loop: {e}", exc_info=True)
            if self.controller.is_processing:
                self.controller.handle_worker_completion({"type": "error", "message": str(e)})

        if self.controller.is_processing:
            self.after(100, self.poll_result_queue)

    def populate_timeline_from_dataframe(self, summary_df: "pd.DataFrame"):
        if summary_df is None or summary_df.empty:
            log.warning("Timeline population skipped: dataframe is empty or None.")
            return

        self.flight_timeline_tree.delete(*self.flight_timeline_tree.get_children())
        for i, row in summary_df.iterrows():
            duration_str = f"{row['Duration (s)']:.2f}"
            self.flight_timeline_tree.insert(
                "",
                "end",
                iid=str(i),
                values=(
                    row["Segment (Mode | Scale | WF)"],
                    row["Start Batch"],
                    row["End Batch"],
                    row["Batch Count"],
                    duration_str,
                    row["Start File"],
                    row["End File"],
                    row["# Files"],
                ),
            )

    def on_close(self):
        if self.controller.is_processing:
            if messagebox.askyesno(
                "Confirm Exit",
                "A process is still running. Are you sure you want to exit?",
            ):
                self.controller.shutdown()
                self.master.destroy()
        else:
            self.controller.shutdown()
            self.master.destroy()