# target_simulator/gui/target_list_frame.py

"""
A frame containing the Treeview for listing targets and control buttons.
"""
import tkinter as tk
from tkinter import ttk, messagebox
from typing import List, Callable, Optional

from target_simulator.core.models import Target, FPS_TO_KNOTS, NM_TO_FT

# Importa il nuovo editor di traiettoria
from .trajectory_editor_window import TrajectoryEditorWindow


class TargetListFrame(ttk.LabelFrame):
    """Frame for displaying and managing the list of targets."""

    def __init__(
        self,
        master,
        targets_changed_callback: Optional[Callable[[List[Target]], None]] = None,
    ):
        super().__init__(master, text="Target List")
        self.targets_cache: List[Target] = []
        self.targets_changed_callback = targets_changed_callback

        # --- Treeview for Targets ---
        columns = ("id", "range", "az", "vel", "hdg", "alt")
        self.tree = ttk.Treeview(self, columns=columns, show="headings")

        self.tree.heading("id", text="ID")
        self.tree.heading("range", text="Range (NM)")
        self.tree.heading("az", text="Azimuth (°)")
        self.tree.heading("vel", text="Velocity (kn)")
        self.tree.heading("hdg", text="Heading (°)")
        self.tree.heading("alt", text="Altitude (ft)")

        self.tree.column("id", width=40, anchor=tk.CENTER)
        self.tree.column("range", width=100, anchor=tk.E)
        self.tree.column("az", width=80, anchor=tk.E)
        self.tree.column("vel", width=100, anchor=tk.E)
        self.tree.column("hdg", width=80, anchor=tk.E)
        self.tree.column("alt", width=100, anchor=tk.E)

        # --- Scrollbar & Layout ---
        scrollbar = ttk.Scrollbar(self, orient=tk.VERTICAL, command=self.tree.yview)
        self.tree.configure(yscroll=scrollbar.set)
        self.tree.grid(row=0, column=0, sticky=tk.NSEW)
        scrollbar.grid(row=0, column=1, sticky=tk.NS)
        self.rowconfigure(0, weight=1)
        self.columnconfigure(0, weight=1)

        # --- Buttons ---
        button_frame = ttk.Frame(self)
        button_frame.grid(row=1, column=0, columnspan=2, pady=5, sticky=tk.W)

        self.add_button = ttk.Button(
            button_frame, text="Add", command=self._on_add_click
        )
        self.add_button.pack(side=tk.LEFT, padx=5)
        self.remove_button = ttk.Button(
            button_frame, text="Remove", command=self._on_remove_click
        )
        self.remove_button.pack(side=tk.LEFT, padx=5)
        self.edit_button = ttk.Button(
            button_frame, text="Edit Trajectory...", command=self._on_edit_click
        )
        self.edit_button.pack(side=tk.LEFT, padx=5)

        self.tree.bind("<Double-1>", self._on_double_click)

    def get_targets(self) -> List[Target]:
        """Returns the current list of targets from the cache."""
        return self.targets_cache

    def _on_add_click(self):
        """Opens the trajectory editor to create a new target."""
        existing_ids = [t.target_id for t in self.targets_cache]

        main_ppi = self.winfo_toplevel().ppi_widget
        editor = TrajectoryEditorWindow(
            self, existing_ids=existing_ids, max_range_nm=main_ppi.max_range
        )

        if editor.result_target:
            self.targets_cache.append(editor.result_target)
            self.update_target_list(self.targets_cache)
            if self.targets_changed_callback:
                self.targets_changed_callback(self.targets_cache)

    def _on_remove_click(self):
        selected_item = self.tree.focus()
        if not selected_item:
            messagebox.showwarning(
                "No Selection", "Please select a target to remove.", parent=self
            )
            return

        try:
            target_id = int(self.tree.item(selected_item, "values")[0])
            self.targets_cache = [
                t for t in self.targets_cache if t.target_id != target_id
            ]
            self.update_target_list(self.targets_cache)
            if self.targets_changed_callback:
                self.targets_changed_callback(self.targets_cache)
        except (ValueError, IndexError):
            messagebox.showerror(
                "Error", "Could not identify the selected target.", parent=self
            )

    def _on_edit_click(self, event=None):
        """Opens the trajectory editor to modify an existing target."""
        selected_item = self.tree.focus()
        if not selected_item:
            if (
                not event
            ):  # Show warning only on button click, not on failed double-click
                messagebox.showwarning(
                    "No Selection", "Please select a target to edit.", parent=self
                )
            return

        try:
            target_id = int(self.tree.item(selected_item, "values")[0])
        except (ValueError, IndexError):
            return  # Fail silently on invalid row data

        target_to_edit = next(
            (t for t in self.targets_cache if t.target_id == target_id), None
        )
        if not target_to_edit:
            messagebox.showerror(
                "Error",
                f"Internal error: Target with ID {target_id} not found in cache.",
                parent=self,
            )
            return

        other_ids = [
            t.target_id for t in self.targets_cache if t.target_id != target_id
        ]
        main_ppi = self.winfo_toplevel().ppi_widget
        # Get scenario name from main view
        scenario_name = None
        toplevel = self.winfo_toplevel()
        if hasattr(toplevel, "current_scenario_name"):
            scenario_name = toplevel.current_scenario_name
        editor = TrajectoryEditorWindow(
            self,
            existing_ids=other_ids,
            target_to_edit=target_to_edit,
            max_range_nm=main_ppi.max_range,
            scenario_name=scenario_name,
        )

        if editor.result_target:
            # Replace the old target object with the new, edited one
            for i, t in enumerate(self.targets_cache):
                if t.target_id == target_id:
                    self.targets_cache[i] = editor.result_target
                    break

            self.update_target_list(self.targets_cache)
            if self.targets_changed_callback:
                self.targets_changed_callback(self.targets_cache)

    def _on_double_click(self, event):
        if self.tree.identify_row(event.y):
            self._on_edit_click(event)

    def update_target_list(self, targets: List[Target]):
        """Clears and repopulates the treeview with the current list of targets."""
        self.targets_cache = list(targets)

        selected_id_str = self.tree.focus()
        selected_id = None
        if selected_id_str:
            try:
                selected_id = int(self.tree.item(selected_id_str, "values")[0])
            except (ValueError, IndexError):
                selected_id = None

        self.tree.delete(*self.tree.get_children())

        new_selection_item = None
        for target in sorted(self.targets_cache, key=lambda t: t.target_id):
            values = (
                target.target_id,
                f"{target.current_range_nm:.2f}",
                f"{target.current_azimuth_deg:.2f}",
                f"{target.current_velocity_fps * FPS_TO_KNOTS:.2f}",
                f"{target.current_heading_deg:.2f}",
                f"{target.current_altitude_ft:.0f}",
            )
            item_id = self.tree.insert("", tk.END, values=values)
            if target.target_id == selected_id:
                new_selection_item = item_id

        if new_selection_item:
            self.tree.focus(new_selection_item)
            self.tree.selection_set(new_selection_item)
