#!/usr/bin/env python3
"""Build NexusOS GTK2 theme from Mint-Y-Dark-Aqua base.

- Copies .rc files + assets/ from /usr/share/themes/Mint-Y-Dark-Aqua/gtk-2.0/
- Recolors PNGs containing the Aqua accent (#1f9ede) to NexusOS green (#8cc63f)
- Rewrites the gtk-color-scheme block in gtkrc to NexusOS palette
- Replaces remaining aqua hex literals in .rc files
"""
from __future__ import annotations

import colorsys
import shutil
import sys
from pathlib import Path

THEMES_ROOT = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(THEMES_ROOT))
import _palette as P  # noqa: E402

from PIL import Image  # noqa: E402

SRC = Path("/usr/share/themes/Mint-Y-Dark-Aqua/gtk-2.0")
OUT = THEMES_ROOT / "NexusOS" / "gtk-2.0"

AQUA_RGB = (0x1F, 0x9E, 0xDE)
AQUA_HSV = colorsys.rgb_to_hsv(*(c / 255 for c in AQUA_RGB))
GREEN_HSV = P.hex_to_hsv(P.BRAND_GREEN)

HUE_TOLERANCE = 30 / 360
SAT_FLOOR = 0.18

S_SCALE = GREEN_HSV[1] / AQUA_HSV[1]
V_SCALE = GREEN_HSV[2] / AQUA_HSV[2]


def hue_distance(a: float, b: float) -> float:
    d = abs(a - b)
    return min(d, 1 - d)


def recolor_pixel(r: int, g: int, b: int, a: int) -> tuple[int, int, int, int]:
    if a < 8:
        return (r, g, b, a)
    h, s, v = colorsys.rgb_to_hsv(r / 255, g / 255, b / 255)
    if s < SAT_FLOOR or hue_distance(h, AQUA_HSV[0]) > HUE_TOLERANCE:
        return (r, g, b, a)
    new_s = min(1.0, s * S_SCALE)
    new_v = min(1.0, v * V_SCALE)
    nr, ng, nb = colorsys.hsv_to_rgb(GREEN_HSV[0], new_s, new_v)
    return (round(nr * 255), round(ng * 255), round(nb * 255), a)


def recolor_png(path: Path) -> int:
    """Recolor aqua pixels in-place. Returns count of pixels changed."""
    im = Image.open(path).convert("RGBA")
    px = im.load()
    w, h = im.size
    changed = 0
    for y in range(h):
        for x in range(w):
            r, g, b, a = px[x, y]
            new = recolor_pixel(r, g, b, a)
            if new != (r, g, b, a):
                px[x, y] = new
                changed += 1
    if changed:
        im.save(path, optimize=True)
    return changed


# ── gtkrc color-scheme block ──────────────────────────────────────────
NEW_COLOR_SCHEME = (
    f"base_color:#{P.BASE_BG}\\n"
    f"fg_color:#{P.TEXT_PRIMARY}\\n"
    f"tooltip_fg_color:#{P.TEXT_PRIMARY}\\n"
    f"selected_bg_color:#{P.BRAND_PURPLE_DARK}\\n"
    f"selected_fg_color:#{P.TEXT_ON_SELECTION}\\n"
    f"text_color:#{P.TEXT_PRIMARY}\\n"
    f"bg_color:#{P.SURFACE_BG}\\n"
    f"insensitive_bg_color:#{P.SURFACE_BG}\\n"
    f"insensitive_fg_color:#{P.TEXT_DISABLED}\\n"
    f"notebook_bg:#{P.BASE_BG}\\n"
    f"dark_sidebar_bg:#{P.SURFACE_BG_ALT}\\n"
    f"tooltip_bg_color:#{P.OVERLAY_BG}\\n"
    f"link_color:#{P.BRAND_GREEN_LIGHT}\\n"
    f"menu_bg:#{P.SURFACE_BG}\\n"
    f"menu_separator_color:#{P.BORDER}"
)


def patch_gtkrc(path: Path) -> None:
    text = path.read_text()
    out_lines = []
    for line in text.splitlines():
        if line.startswith("gtk-color-scheme"):
            out_lines.append(f'gtk-color-scheme = "{NEW_COLOR_SCHEME}"')
        else:
            out_lines.append(line)
    path.write_text("\n".join(out_lines) + "\n")


# ── Remaining hex literals in .rc files ───────────────────────────────
# Captured from Mint-Y-Dark-Aqua; map source hex → NexusOS replacement.
RC_HEX_REPLACEMENTS = {
    # accent / focus / selection
    "#1f9ede": f"#{P.BRAND_GREEN}",
    "#1F9EDE": f"#{P.BRAND_GREEN}",
    "#5294E2": f"#{P.BRAND_GREEN_LIGHT}",  # link_color fallback if quoted literal
    "#5294e2": f"#{P.BRAND_GREEN_LIGHT}",
    # Mint-Y greys we want to nudge onto our surface family
    "#2b2b2b": f"#{P.SURFACE_BG_ALT}",
    "#383838": f"#{P.SURFACE_BG}",
    "#404040": f"#{P.BASE_BG}",
    "#3e3e3e": f"#{P.SURFACE_BG}",
    "#dadada": f"#{P.TEXT_PRIMARY}",
    "#DADADA": f"#{P.TEXT_PRIMARY}",
    "#d3d3d3": f"#{P.TEXT_PRIMARY}",
    "#D3D3D3": f"#{P.TEXT_PRIMARY}",
}


def patch_rc(path: Path) -> int:
    text = path.read_text()
    count = 0
    for src, dst in RC_HEX_REPLACEMENTS.items():
        n = text.count(src)
        if n:
            text = text.replace(src, dst)
            count += n
    path.write_text(text)
    return count


def main() -> None:
    if OUT.exists():
        shutil.rmtree(OUT)
    shutil.copytree(SRC, OUT)
    print(f"Copied {SRC} → {OUT}")

    # Recolor PNGs
    recolored = 0
    for png in sorted((OUT / "assets").glob("*.png")):
        changed = recolor_png(png)
        if changed:
            recolored += 1
            print(f"  recolored {png.name}: {changed}px")
    print(f"Recolored {recolored} PNGs")

    # Patch rc files
    patched_total = 0
    for rc in sorted(OUT.glob("*.rc")):
        n = patch_rc(rc)
        if n:
            print(f"  patched {rc.name}: {n} replacements")
            patched_total += n
    gtkrc = OUT / "gtkrc"
    patch_rc(gtkrc)
    patch_gtkrc(gtkrc)
    print(f"Rewrote gtkrc color scheme; total .rc hex replacements: {patched_total}")


if __name__ == "__main__":
    main()
