from importlib.util import module_from_spec, spec_from_file_location
from pathlib import Path

from kitty.fast_data_types import Color
from kitty.tab_bar import DrawData, ExtraData, TabBarData, as_rgb


class Cursor:
    x = 0
    fg = as_rgb(0xFEDCBA)
    bg = as_rgb(0xABCDEF)


class RecordingScreen:
    def __init__(self) -> None:
        self.cursor = Cursor()
        self.draws: list[tuple[str, int, int]] = []

    def draw(self, text: str) -> None:
        self.draws.append((text, self.cursor.fg, self.cursor.bg))
        self.cursor.x += len(text)


def load_renderer():
    path = Path.cwd() / "tab_bar.py"
    spec = spec_from_file_location("kitty_user_tab_bar", path)
    if spec is None or spec.loader is None:
        raise RuntimeError(f"cannot load {path}")
    module = module_from_spec(spec)
    spec.loader.exec_module(module)
    return module


def draw_data(theme_bg: int) -> DrawData:
    return DrawData(
        0,
        "",
        0,
        "",
        (),
        Color(0x11, 0x11, 0x11),
        Color(0xAB, 0xCD, 0xEF),
        Color(0xFE, 0xDC, 0xBA),
        Color(0x22, 0x22, 0x22),
        Color((theme_bg >> 16) & 0xFF, (theme_bg >> 8) & 0xFF, theme_bg & 0xFF),
        "",
        None,
        "",
        "default",
        "top",
        0,
        0,
    )


renderer = load_renderer()
for theme_bg in (0xF8F8F8, 0x1C2836):
    roles = renderer.tab_colors(draw_data(theme_bg).default_bg)
    actual_roles = tuple(int(value) for value in roles)
    expected_roles = (theme_bg, 0x2E84E6, 0x2E84E6, theme_bg)
    if actual_roles != expected_roles:
        raise RuntimeError(
            f"theme #{theme_bg:06x}: expected roles {expected_roles!r}, "
            f"got {actual_roles!r}"
        )

    for is_active, expected in (
        (True, (as_rgb(theme_bg), as_rgb(0x2E84E6))),
        (False, (as_rgb(0x2E84E6), as_rgb(theme_bg))),
    ):
        screen = RecordingScreen()
        renderer.draw_tab(
            draw_data(theme_bg),
            screen,
            TabBarData("tab", is_active=is_active),
            0,
            1,
            1,
            True,
            ExtraData(),
        )
        _, actual_fg, actual_bg = screen.draws[0]
        if (actual_fg, actual_bg) != expected:
            raise RuntimeError(
                f"theme #{theme_bg:06x}, active={is_active}: "
                f"expected cursor colors {expected!r}, "
                f"got {(actual_fg, actual_bg)!r}"
            )

print(
    "PASS: tab colors ignore theme-provided tab roles "
    "for light and dark backgrounds"
)
