# target_simulator/gui/simulation_controls.py

import tkinter as tk
from tkinter import ttk
from typing import Dict, Any, List
import math

from target_simulator.core.models import FPS_TO_KNOTS, Target


class SimulationControls(ttk.LabelFrame):
    """
    Encapsulates the Live Simulation Engine controls, ownship status,
    and active targets display.
    """

    def __init__(self, parent, main_view):
        super().__init__(parent, text="Live Simulation Engine")
        self.main_view = main_view

        # --- Variables for UI Binding ---
        self.time_multiplier_var = getattr(
            main_view, "time_multiplier_var", tk.StringVar(value="1x")
        )
        self.update_time = getattr(main_view, "update_time", tk.DoubleVar(value=1.0))
        self.sim_slider_var = getattr(
            main_view, "sim_slider_var", tk.DoubleVar(value=0.0)
        )

        # Ownship display variables
        self.lat_var = tk.StringVar(value="-")
        self.lon_var = tk.StringVar(value="-")
        self.alt_var = tk.StringVar(value="-")
        self.hdg_var = tk.StringVar(value="-")
        self.gnd_speed_var = tk.StringVar(value="-")
        self.vert_speed_var = tk.StringVar(value="-")

        # --- Widget Layout ---
        self.grid_columnconfigure(0, weight=1)

        # Main controls frame
        controls_frame = ttk.Frame(self)
        controls_frame.grid(row=0, column=0, sticky="ew", padx=5, pady=5)
        controls_frame.grid_columnconfigure(3, weight=1)

        self.start_button = ttk.Button(
            controls_frame, text="Start Live", command=self._start
        )
        self.start_button.grid(row=0, column=0, sticky="w")

        self.stop_button = ttk.Button(
            controls_frame, text="Stop Live", command=self._stop, state=tk.DISABLED
        )
        self.stop_button.grid(row=0, column=1, sticky="w", padx=5)

        ttk.Frame(controls_frame).grid(row=0, column=2, sticky="ew", padx=10)  # Spacer

        ttk.Label(controls_frame, text="Speed:").grid(
            row=0, column=4, sticky="e", padx=(10, 2)
        )
        self.multiplier_combo = ttk.Label(
            controls_frame, text="1x"
        )  # Placeholder, could be a combo
        self.multiplier_combo.grid(row=0, column=5, sticky="w")

        ttk.Label(controls_frame, text="Update (s):").grid(
            row=0, column=6, sticky="e", padx=(10, 2)
        )
        self.update_time_entry = ttk.Entry(
            controls_frame, textvariable=self.update_time, width=5
        )
        self.update_time_entry.grid(row=0, column=7, sticky="w")

        self.reset_button = ttk.Button(
            controls_frame,
            text="Reset Sim",
            command=getattr(main_view, "_on_reset_simulation", lambda: None),
        )
        self.reset_button.grid(row=0, column=8, sticky="e", padx=10)

        self.reset_radar_button = ttk.Button(
            controls_frame,
            text="Reset Radar",
            command=getattr(main_view, "_reset_radar_state", lambda: None),
        )
        self.reset_radar_button.grid(row=0, column=9, sticky="e")

        # Progress slider row
        progress_frame = ttk.Frame(self)
        progress_frame.grid(row=1, column=0, sticky="ew", padx=5, pady=(6, 2))
        progress_frame.grid_columnconfigure(0, weight=1)

        self.sim_slider = ttk.Scale(
            progress_frame,
            orient=tk.HORIZONTAL,
            variable=self.sim_slider_var,
            from_=0.0,
            to=1.0,
        )
        self.sim_slider.grid(row=0, column=0, sticky="ew", padx=(4, 8))
        self.sim_slider.bind(
            "<ButtonPress-1>", lambda e: setattr(main_view, "_slider_is_dragging", True)
        )
        self.sim_slider.bind(
            "<ButtonRelease-1>",
            lambda e: (
                setattr(main_view, "_slider_is_dragging", False),
                getattr(main_view, "_on_seek", lambda: None)(),
            ),
        )

        labels_frame = ttk.Frame(progress_frame)
        labels_frame.grid(row=0, column=1, sticky="e")
        self.sim_elapsed_label = ttk.Label(
            labels_frame, text="0.0s", width=8, anchor=tk.E
        )
        self.sim_elapsed_label.pack(side=tk.LEFT)
        ttk.Label(labels_frame, text="/").pack(side=tk.LEFT, padx=2)
        self.sim_total_label = ttk.Label(
            labels_frame, text="0.0s", width=8, anchor=tk.W
        )
        self.sim_total_label.pack(side=tk.LEFT)

        # --- Ownship State Display ---
        ownship_frame = ttk.LabelFrame(self, text="Ownship State", padding=10)
        ownship_frame.grid(row=2, column=0, sticky="ew", padx=5, pady=8)
        ownship_frame.grid_columnconfigure(1, weight=1)
        ownship_frame.grid_columnconfigure(3, weight=1)
        ownship_frame.grid_columnconfigure(5, weight=1)

        ttk.Label(ownship_frame, text="Latitude:").grid(row=0, column=0, sticky="w")
        ttk.Label(ownship_frame, textvariable=self.lat_var, anchor="w").grid(
            row=0, column=1, sticky="ew", padx=5
        )

        ttk.Label(ownship_frame, text="Longitude:").grid(row=1, column=0, sticky="w")
        ttk.Label(ownship_frame, textvariable=self.lon_var, anchor="w").grid(
            row=1, column=1, sticky="ew", padx=5
        )

        ttk.Label(ownship_frame, text="Altitude:").grid(
            row=0, column=2, sticky="w", padx=(10, 0)
        )
        ttk.Label(ownship_frame, textvariable=self.alt_var, anchor="w").grid(
            row=0, column=3, sticky="ew", padx=5
        )

        ttk.Label(ownship_frame, text="Heading:").grid(
            row=1, column=2, sticky="w", padx=(10, 0)
        )
        ttk.Label(ownship_frame, textvariable=self.hdg_var, anchor="w").grid(
            row=1, column=3, sticky="ew", padx=5
        )

        ttk.Label(ownship_frame, text="Ground Speed:").grid(
            row=0, column=4, sticky="w", padx=(10, 0)
        )
        ttk.Label(ownship_frame, textvariable=self.gnd_speed_var, anchor="w").grid(
            row=0, column=5, sticky="ew", padx=5
        )

        ttk.Label(ownship_frame, text="Vertical Speed:").grid(
            row=1, column=4, sticky="w", padx=(10, 0)
        )
        ttk.Label(ownship_frame, textvariable=self.vert_speed_var, anchor="w").grid(
            row=1, column=5, sticky="ew", padx=5
        )

        # --- Active Targets Table ---
        targets_frame = ttk.LabelFrame(self, text="Active Targets", padding=10)
        targets_frame.grid(row=3, column=0, sticky="nsew", padx=5, pady=8)
        self.grid_rowconfigure(3, weight=1)  # Allow this frame to expand vertically
        targets_frame.grid_columnconfigure(0, weight=1)
        targets_frame.grid_rowconfigure(0, weight=1)

        # Scrollbar
        scrollbar = ttk.Scrollbar(targets_frame, orient=tk.VERTICAL)

        # Treeview
        columns = (
            "id",
            "lat",
            "lon",
            "alt",
            "hdg",
            "gnd_speed",
            "vert_speed",
        )
        self.targets_tree = ttk.Treeview(
            targets_frame,
            columns=columns,
            show="headings",
            yscrollcommand=scrollbar.set,
        )
        scrollbar.config(command=self.targets_tree.yview)

        # Define headings
        self.targets_tree.heading("id", text="ID")
        self.targets_tree.heading("lat", text="Latitude")
        self.targets_tree.heading("lon", text="Longitude")
        self.targets_tree.heading("alt", text="Altitude (ft)")
        self.targets_tree.heading("hdg", text="Heading (°)")
        self.targets_tree.heading("gnd_speed", text="Speed (kn)")
        self.targets_tree.heading("vert_speed", text="Vert. Speed (ft/s)")

        # Define column properties
        self.targets_tree.column("id", width=30, anchor=tk.CENTER, stretch=False)
        self.targets_tree.column("lat", width=100, anchor=tk.W)
        self.targets_tree.column("lon", width=100, anchor=tk.W)
        self.targets_tree.column("alt", width=80, anchor=tk.E)
        self.targets_tree.column("hdg", width=80, anchor=tk.E)
        self.targets_tree.column("gnd_speed", width=80, anchor=tk.E)
        self.targets_tree.column("vert_speed", width=100, anchor=tk.E)

        # Layout Treeview and Scrollbar
        self.targets_tree.grid(row=0, column=0, sticky="nsew")
        scrollbar.grid(row=0, column=1, sticky="ns")

        # --- Non-modal notice area ---
        self.notice_var = tk.StringVar(value="")
        self.notice_frame = ttk.Frame(self)
        self.notice_frame.grid(row=4, column=0, sticky="ew", padx=5, pady=(5, 0))
        self.notice_frame.grid_remove()  # Hidden by default

        notice_label = tk.Label(
            self.notice_frame,
            textvariable=self.notice_var,
            bg="#fff3cd",
            fg="#6a4b00",
            anchor="w",
            relief=tk.SOLID,
            bd=1,
            padx=6,
            pady=2,
        )
        notice_label.pack(side=tk.LEFT, fill=tk.X, expand=True)
        ttk.Button(self.notice_frame, text="Dismiss", command=self.hide_notice).pack(
            side=tk.RIGHT, padx=(6, 0)
        )

    def update_ownship_display(self, state: Dict[str, Any]):
        """Updates the labels in the Ownship State frame."""
        if not state:
            self.lat_var.set("-")
            self.lon_var.set("-")
            self.alt_var.set("-")
            self.hdg_var.set("-")
            self.gnd_speed_var.set("-")
            self.vert_speed_var.set("-")
            return

        # Latitude / Longitude
        lat = state.get("latitude", 0.0)
        lon = state.get("longitude", 0.0)
        self.lat_var.set(f"{abs(lat):.5f}° {'N' if lat >= 0 else 'S'}")
        self.lon_var.set(f"{abs(lon):.5f}° {'E' if lon >= 0 else 'W'}")

        # Altitude
        alt_ft = state.get("altitude_ft", 0.0)
        self.alt_var.set(f"{alt_ft:.1f} ft")

        # Heading
        hdg_deg = state.get("heading_deg", 0.0)
        self.hdg_var.set(f"{hdg_deg:.2f}°")

        # Ground Speed
        vx_fps, vy_fps = state.get("velocity_xy_fps", (0.0, 0.0))
        gnd_speed_kn = (vx_fps**2 + vy_fps**2) ** 0.5 * FPS_TO_KNOTS
        self.gnd_speed_var.set(f"{gnd_speed_kn:.1f} kn")

        # Vertical Speed
        vz_fps = state.get("velocity_z_fps", 0.0)
        self.vert_speed_var.set(f"{vz_fps:+.1f} ft/s")

    def update_targets_table(
        self, targets: List[Target], ownship_state: Dict[str, Any]
    ):
        """Clears and repopulates the active targets table with geographic data."""
        for item in self.targets_tree.get_children():
            self.targets_tree.delete(item)

        # Get ownship data needed for conversion
        own_lat = ownship_state.get("latitude")
        own_lon = ownship_state.get("longitude")
        own_pos_xy_ft = ownship_state.get("position_xy_ft")

        for target in sorted(targets, key=lambda t: t.target_id):
            if not target.active:
                continue

            lat_str = "N/A"
            lon_str = "N/A"

            # Calculate geographic position if possible
            if own_lat is not None and own_lon is not None and own_pos_xy_ft:
                target_x_ft = getattr(target, "_pos_x_ft", 0.0)
                target_y_ft = getattr(target, "_pos_y_ft", 0.0)
                own_x_ft, own_y_ft = own_pos_xy_ft

                # Delta from ownship's current position in meters
                delta_east_m = (target_x_ft - own_x_ft) * 0.3048
                delta_north_m = (target_y_ft - own_y_ft) * 0.3048

                # Equirectangular approximation for lat/lon calculation
                earth_radius_m = 6378137.0
                dlat = (delta_north_m / earth_radius_m) * (180.0 / math.pi)
                dlon = (
                    delta_east_m / (earth_radius_m * math.cos(math.radians(own_lat)))
                ) * (180.0 / math.pi)

                target_lat = own_lat + dlat
                target_lon = own_lon + dlon

                lat_str = f"{abs(target_lat):.5f}° {'N' if target_lat >= 0 else 'S'}"
                lon_str = f"{abs(target_lon):.5f}° {'E' if target_lon >= 0 else 'W'}"

            alt_str = f"{target.current_altitude_ft:.1f}"
            hdg_str = f"{target.current_heading_deg:.2f}"

            # Use the now-correct velocity values from the Target object
            gnd_speed_kn = target.current_velocity_fps * FPS_TO_KNOTS
            gnd_speed_str = f"{gnd_speed_kn:.1f}"

            vert_speed_fps = target.current_vertical_velocity_fps
            vert_speed_str = f"{vert_speed_fps:+.1f}"

            values = (
                target.target_id,
                lat_str,
                lon_str,
                alt_str,
                hdg_str,
                gnd_speed_str,
                vert_speed_str,
            )
            self.targets_tree.insert("", tk.END, values=values)

    def show_notice(self, message: str):
        self.notice_var.set(message)
        self.notice_frame.grid()

    def hide_notice(self):
        self.notice_var.set("")
        self.notice_frame.grid_remove()

    def _start(self):
        if hasattr(self.main_view, "_on_start_simulation"):
            self.main_view._on_start_simulation()

    def _stop(self):
        if hasattr(self.main_view, "_on_stop_simulation"):
            self.main_view._on_stop_simulation()
