#!/usr/bin/env python3
"""Runs on THIS host only -- builds a local staging tree mirroring
~/.local/share/icons/hicolor/{scalable,48x48,64x64,128x128}/{apps,status}/
from the portable silhouettes in generated_icons/silhouettes/, stamping in
the current accent color. scripts/11-deploy-icon-theme.sh tars+pushes that
staging tree to the target in one shot -- the target itself needs no
python3/potrace/rsvg-convert for this step, just tar/base64 (standard on
any Linux), which is what makes this step reusable against a brand-new
CachyOS install straight from this repo.
"""
import argparse
import json
import re
import subprocess
from pathlib import Path

PLACEHOLDER = "__ACCENT__"
RASTER_SIZES = (48, 64, 128)

# Both configured theme names on this setup (GTK's "kora", rofi's hardcoded
# "Tela-circle-dracula") turn out not to be installed at all, so lookups
# bottom out on hicolor in practice -- but some Qt apps go through qt6ct's
# own icon_theme setting (breeze-dark here) instead. Installing into both
# covers each path without needing to know exactly which one a given
# consumer uses.
INSTALL_THEMES = ["hicolor", "breeze-dark"]


def parse_size_from_relpath(relpath):
    """Pulls a pixel size out of a relative path like "128x128/apps/x.png"
    or breeze/kora's inverted "apps/128/x.png" -- None for "scalable"."""
    for part in relpath.split("/"):
        if part == "scalable":
            return None
        m = re.match(r"(\d+)", part)
        if m:
            return int(m.group(1))
    return None


def install_exact_override(name, text, theme, relpath, staging):
    """Overrides the icon at the EXACT theme + relative path it was really
    resolved from (e.g. kora's user-local apps/scalable/Alacritty.svg) --
    the standard XDG per-user override ($HOME/.local/share/icons/<theme>/
    <relpath> shadows the system copy in that same theme), which is what
    actually matters when the resolved theme isn't hicolor/breeze-dark at
    all (kora, breeze, Adwaita, ...)."""
    if not theme or not relpath:
        return  # unthemed source (e.g. /usr/share/pixmaps) -- no theme to override
    out = staging / theme / relpath
    out.parent.mkdir(parents=True, exist_ok=True)
    if relpath.lower().endswith(".svg"):
        out.write_text(text)
    else:
        size = parse_size_from_relpath(relpath) or 256
        with_tmp = out.with_suffix(".svg.tmp")
        with_tmp.write_text(text)
        try:
            subprocess.run(
                ["rsvg-convert", "-w", str(size), "-h", str(size), str(with_tmp), "-o", str(out)],
                check=True, capture_output=True,
            )
        finally:
            with_tmp.unlink()


def main():
    ap = argparse.ArgumentParser()
    ap.add_argument("--silhouette-dir", required=True)
    ap.add_argument("--manifest", required=True)
    ap.add_argument("--colors", required=True, help="path to the target's colors.json")
    ap.add_argument("--staging-dir", required=True)
    args = ap.parse_args()

    manifest = json.loads(Path(args.manifest).read_text())
    accent = json.loads(Path(args.colors).read_text())["primary"]
    staging = Path(args.staging_dir)

    silhouettes = sorted(Path(args.silhouette_dir).glob("*.svg"))
    if not silhouettes:
        print("No silhouettes found -- run 10-generate-app-icons.sh first.")
        return

    for svg_path in silhouettes:
        name = svg_path.stem
        entry = manifest.get(name, {})
        is_status = entry.get("is_status", False)
        contexts = ["apps"] + (["status"] if is_status else [])
        text = svg_path.read_text().replace(PLACEHOLDER, accent)

        install_exact_override(name, text, entry.get("source_theme"), entry.get("source_relpath"), staging)

        for theme in INSTALL_THEMES:
            scalable_svgs = []
            for ctx in contexts:
                d = staging / theme / "scalable" / ctx
                d.mkdir(parents=True, exist_ok=True)
                out = d / f"{name}.svg"
                out.write_text(text)
                scalable_svgs.append(out)

            for size in RASTER_SIZES:
                for ctx, svg_out in zip(contexts, scalable_svgs):
                    d = staging / theme / f"{size}x{size}" / ctx
                    d.mkdir(parents=True, exist_ok=True)
                    subprocess.run(
                        ["rsvg-convert", "-w", str(size), "-h", str(size),
                         str(svg_out), "-o", str(d / f"{name}.png")],
                        check=True, capture_output=True,
                    )

    print(f">>> Staged {len(silhouettes)} icon(s) at accent {accent} "
          f"into {', '.join(INSTALL_THEMES)} -> {staging}")


if __name__ == "__main__":
    main()
