from utilities.animator import Animator
from utilities.landmarks import get_nearest_landmark
from setup import colours, fonts, screen
from config import DISTANCE_UNITS
from rgbmatrix import graphics

try:
    from config import SPEED_UNITS
except (ImportError, ModuleNotFoundError, NameError):
    SPEED_UNITS = "knots"


LINE3_Y = 31
FONT = fonts.small

TIME_DIST_COLOUR = colours.LIGHT_MID_BLUE
STATS_COLOUR = colours.LIGHT_PINK
LABEL_COLOUR = colours.LIGHT_GREY
AIRCRAFT_COLOUR = colours.WHITE
SEPARATOR_COLOUR = colours.LIGHT_DARK_GREY


def _format_altitude(altitude):
    if not altitude:
        return None, None
    altitude = int(altitude)
    if DISTANCE_UNITS == "metric":
        metres = int(altitude * 0.3048)
        return str(metres), "m"
    if altitude >= 18000:
        return f"FL{altitude // 100}", ""
    return f"{altitude:,}", "ft"


def _format_speed(ground_speed):
    if not ground_speed:
        return None, None
    if SPEED_UNITS == "imperial":
        return f"{int(ground_speed * 1.15078)}", "mph"
    if SPEED_UNITS == "metric":
        return f"{int(ground_speed * 1.852)}", "km/h"
    return f"{int(ground_speed)}", "kt"


def _build_stats(data):
    parts = []

    def add_field(label, value, value_colour=STATS_COLOUR):
        if value in (None, ""):
            return
        if parts:
            parts.extend((ch, SEPARATOR_COLOUR) for ch in " | ")
        parts.extend((ch, LABEL_COLOUR) for ch in f"{label} ")
        parts.extend((ch, value_colour) for ch in str(value))

    if data.get("time_remaining"):
        add_field("REMAIN", data["time_remaining"], TIME_DIST_COLOUR)

    if data.get("dist_remaining") is not None:
        unit = "km" if DISTANCE_UNITS == "metric" else (
            "nm" if DISTANCE_UNITS == "nautical" else "mi"
        )
        add_field("DIST", f"{int(data['dist_remaining'])}{unit}", TIME_DIST_COLOUR)

    aircraft = data.get("aircraft_type", "")
    if aircraft and aircraft not in ("", "N/A"):
        add_field("TYPE", aircraft, AIRCRAFT_COLOUR)

    alt_val, alt_unit = _format_altitude(data.get("altitude"))
    if alt_val:
        altitude = f"{alt_val}{alt_unit}"
        vertical_speed = data.get("vertical_speed", 0) or 0
        if vertical_speed > 64:
            altitude += "^"
        elif vertical_speed < -64:
            altitude += "v"
        add_field("ALT", altitude)

    speed_val, speed_unit = _format_speed(data.get("ground_speed"))
    if speed_val:
        add_field("GS", f"{speed_val}{speed_unit}")

    heading = data.get("heading")
    if heading is not None:
        add_field("HDG", f"{int(heading):03d}")

    latitude = data.get("latitude")
    longitude = data.get("longitude")
    if latitude is not None and longitude is not None:
        nearest = get_nearest_landmark(latitude, longitude)
        if nearest:
            add_field("NEAR", nearest["name"], colours.WHITE)

    return parts


class TrackedStatsScene(object):
    def __init__(self):
        super().__init__()
        self._ts_pos = screen.WIDTH
        self._ts_len = 0
        self._ts_active = False

    def _clear_tracked_stats(self):
        self.draw_square(0, LINE3_Y - 6, screen.WIDTH, LINE3_Y, colours.BLACK)
        self._ts_active = False

    @Animator.KeyFrame.add(0)
    def reset_tracked_stats_scroll(self):
        self._ts_pos = screen.WIDTH
        self._ts_len = 0

    @Animator.KeyFrame.add(1)
    def tracked_stats(self, count):
        tracked = self.overhead.tracked_data
        if not tracked or tracked.get("pre_flight"):
            if self._ts_active:
                self._clear_tracked_stats()
            return
        if len(self._data) > 0:
            if not tracked.get("override_flights"):
                if self._ts_active:
                    self._clear_tracked_stats()
                return
        elif not tracked.get("override_idle", True):
            if self._ts_active:
                self._clear_tracked_stats()
            return
        if tracked.get("waiting_live"):
            self._clear_tracked_stats()
            return

        char_list = _build_stats(tracked)
        self.draw_square(0, LINE3_Y - 6, screen.WIDTH, LINE3_Y, colours.BLACK)
        self._ts_active = True

        total_len = 0
        for ch, colour in char_list:
            total_len += graphics.DrawText(
                self.canvas,
                FONT,
                self._ts_pos + total_len,
                LINE3_Y,
                colour,
                ch,
            )
        self._ts_len = total_len
        self._ts_pos -= 1

        if self._ts_pos + self._ts_len < 0:
            self._ts_pos = screen.WIDTH
