from PIL import Image

from utilities.animator import Animator
from setup import colours, fonts, screen
from rgbmatrix import graphics


HEADER_BOTTOM = 15
LOGO_SIZE = 12
LOGO_X = 1
LOGO_Y = 1
TEXT_X = LOGO_X + LOGO_SIZE + 2
NAME_Y = 6
ROUTE_Y = 13
FONT = fonts.extrasmall
DEFAULT_IMAGE = "default"

NAME_COLOUR = colours.WHITE
NUMBER_COLOUR = colours.LIGHT_ORANGE
ROUTE_COLOUR = colours.LIGHT_MID_BLUE


def _load_logo(airline_icao):
    icao = airline_icao if airline_icao and airline_icao not in ("", "N/A") else DEFAULT_IMAGE
    try:
        image = Image.open(f"logos/{icao}.png")
    except FileNotFoundError:
        try:
            image = Image.open(f"logos/{DEFAULT_IMAGE}.png")
        except FileNotFoundError:
            return None
    try:
        resample = Image.Resampling.LANCZOS
    except AttributeError:
        resample = Image.ANTIALIAS
    return image.resize((LOGO_SIZE, LOGO_SIZE), resample).convert("RGB")


def _draw_logo(canvas, image):
    if image is None:
        return
    for py in range(LOGO_SIZE):
        for px in range(LOGO_SIZE):
            r, g, b = image.getpixel((px, py))
            canvas.SetPixel(LOGO_X + px, LOGO_Y + py, r, g, b)


def _fit_text(text, width_pixels):
    max_chars = max(1, width_pixels // 4)
    text = str(text or "")
    if len(text) <= max_chars:
        return text
    if max_chars <= 3:
        return text[:max_chars]
    return text[:max_chars - 3].rstrip() + "..."


def _airline_icao(data):
    code = str(data.get("airline_icao") or "").strip().upper()
    if code:
        return code
    callsign = str(data.get("callsign") or "").strip().upper()
    prefix = "".join(ch for ch in callsign if ch.isalpha())
    return prefix[:3] if len(prefix) >= 3 else DEFAULT_IMAGE


class TrackedRouteScene(object):
    def __init__(self):
        super().__init__()
        self._tr_logo = None
        self._tr_last_icao = None
        self._tr_active = False

    def _clear_tracked_route(self):
        self.draw_square(0, 0, screen.WIDTH, HEADER_BOTTOM, colours.BLACK)
        self._tr_active = False

    @Animator.KeyFrame.add(0)
    def reset_tracked_route(self):
        self._tr_last_icao = None
        self._tr_logo = None

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

        self.draw_square(0, 0, screen.WIDTH, HEADER_BOTTOM, colours.BLACK)
        self._tr_active = True

        airline_icao = _airline_icao(tracked)
        if airline_icao != self._tr_last_icao:
            self._tr_logo = _load_logo(airline_icao)
            self._tr_last_icao = airline_icao
        _draw_logo(self.canvas, self._tr_logo)

        available_width = screen.WIDTH - TEXT_X
        number = tracked.get("number") or tracked.get("callsign") or "TRACKED"
        if tracked.get("waiting_live"):
            name_text = f"{number} waiting"
            route_text = "Waiting live data"
        else:
            airline = tracked.get("airline_name") or airline_icao
            name_text = f"{number} {airline}".strip()
            origin = tracked.get("origin") or "???"
            destination = tracked.get("destination") or "???"
            route_text = f"{origin}>{destination}"

        name_text = _fit_text(name_text, available_width)
        route_text = _fit_text(route_text, available_width)

        x = TEXT_X
        for ch in name_text:
            colour = NUMBER_COLOUR if ch.isnumeric() else NAME_COLOUR
            x += graphics.DrawText(self.canvas, FONT, x, NAME_Y, colour, ch)

        graphics.DrawText(self.canvas, FONT, TEXT_X, ROUTE_Y, ROUTE_COLOUR, route_text)
