from rgbmatrix import graphics
from utilities.animator import Animator
from utilities.tracked_display import tracked_overrides_flights
from setup import colours, fonts, screen
from config import DISTANCE_UNITS

try:
    from config import DISPLAY_FIELDS
except Exception:
    DISPLAY_FIELDS = {}

PLANE_COLOUR = colours.LIGHT_MID_BLUE
PLANE_DISTANCE_COLOUR = colours.LIGHT_PINK
ALTITUDE_COLOUR = colours.LIGHT_PINK
CLIMB_COLOUR = colours.LIGHT_GREEN
DESCEND_COLOUR = colours.LIGHT_LIGHT_RED
PLANE_DISTANCE_FROM_TOP = 31
PLANE_TEXT_HEIGHT = 6
PLANE_FONT = fonts.small
DEFAULT_FIELDS = ["plane", "home_distance", "direction", "altitude", "vertical_speed"]


def _dist_unit():
    if DISTANCE_UNITS == "imperial":
        return "mi"
    if DISTANCE_UNITS == "metric":
        return "km"
    return "nm"


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


def _flight_number(data):
    callsign = data.get("callsign", "")
    owner_icao = data.get("owner_icao", "")
    if callsign and owner_icao and callsign.startswith(owner_icao):
        return callsign[len(owner_icao):]
    return callsign


def _field_text(field, data):
    unit = _dist_unit()
    if field == "plane":
        return data.get("plane", "")
    if field == "home_distance":
        value = data.get("distance")
        return f"{float(value):.2f}{unit}" if value not in ("", None) else ""
    if field == "direction":
        return data.get("direction", "")
    if field == "altitude":
        alt_val, alt_unit = _format_altitude(data.get("altitude", 0))
        return f"{alt_val}{alt_unit}" if alt_val else ""
    if field == "vertical_speed":
        vs = data.get("vertical_speed") or 0
        if vs > 64:
            return "^"
        if vs < -64:
            return "v"
        return ""
    if field == "ground_speed":
        value = data.get("ground_speed")
        return f"{int(value)}kt" if value not in ("", None) else ""
    if field == "heading":
        value = data.get("heading")
        return f"{int(value)}deg" if value not in ("", None) else ""
    if field == "flight_number":
        return _flight_number(data)
    if field in ("distance_origin", "distance_destination"):
        value = data.get(field)
        return f"{float(value):.0f}{unit}" if value not in ("", None) else ""
    value = data.get(field)
    return str(value) if value not in ("", None, "N/A") else ""


def _field_colour(field, data):
    if field == "plane":
        return PLANE_COLOUR
    if field in ("home_distance", "direction", "distance_origin", "distance_destination"):
        return PLANE_DISTANCE_COLOUR
    if field in ("altitude", "ground_speed", "heading"):
        return ALTITUDE_COLOUR
    if field == "vertical_speed":
        vs = data.get("vertical_speed") or 0
        if vs > 64:
            return CLIMB_COLOUR
        if vs < -64:
            return DESCEND_COLOUR
    return PLANE_COLOUR


def _build_char_list(data):
    parts = []
    fields = DISPLAY_FIELDS.get("plane_details", DEFAULT_FIELDS) or DEFAULT_FIELDS
    for field in fields:
        text = _field_text(field, data)
        if not text:
            continue
        colour = _field_colour(field, data)
        if parts:
            parts.append((" ", colour))
        for ch in text:
            parts.append((ch, colour))
    return parts


class PlaneDetailsScene(object):
    def __init__(self):
        super().__init__()
        self.plane_position = screen.WIDTH
        self.plane_details_complete = False
        self._data_all_looped = False

    @Animator.KeyFrame.add(1)
    def plane_details(self, count):
        if tracked_overrides_flights(self.overhead):
            return

        if len(self._data) == 0:
            return

        if self.plane_details_complete:
            return

        plane_data = self._data[self._data_index]
        char_list = _build_char_list(plane_data)

        self.draw_square(
            0,
            PLANE_DISTANCE_FROM_TOP - PLANE_TEXT_HEIGHT,
            screen.WIDTH,
            screen.HEIGHT,
            colours.BLACK,
        )

        total_text_width = 0
        for ch, colour in char_list:
            w = graphics.DrawText(
                self.canvas,
                PLANE_FONT,
                self.plane_position + total_text_width,
                PLANE_DISTANCE_FROM_TOP,
                colour,
                ch,
            )
            total_text_width += w

        self.plane_position -= 1

        if self.plane_position + total_text_width < 0:
            if len(self._data) > 1:
                self.plane_details_complete = True
                self.mark_scroll_complete("plane_details")
            else:
                self.plane_position = screen.WIDTH

    @Animator.KeyFrame.add(0)
    def reset_plane_details_scroll(self):
        self.plane_position = screen.WIDTH
        self.plane_details_complete = False
