#!/usr/bin/env bash
# Install the Adom theme system onto this machine:
#   1. the skill (always) -> ~/.claude/skills/adom-theme/
#   2. the VS Code theme pack (when code-server is present) -> makes the five
#      "Adom ..." themes selectable in the editor. Does NOT change the active
#      theme; that stays the user's choice.
#   3. the brand fonts:
#      - JetBrains Mono + Familjen Grotesk ship IN this package (OFL 1.1).
#      - Satoshi is fetched from Fontshare's OFFICIAL servers at install time;
#        its EULA forbids re-hosting the files publicly but blesses delivery
#        from Indian Type Foundry's own servers. See fonts/satoshi/README.md.
set -euo pipefail
HERE="$(cd "$(dirname "$0")" && pwd)"
log() { echo "[adom-theme] $*"; }

# --- 1. the skill ------------------------------------------------------------
DEST="$HOME/.claude/skills/adom-theme"
# migrate: drop the pre-rename skill dir so only one copy exists
rm -rf "$HOME/.claude/skills/adom-theme-system"
mkdir -p "$DEST"
cp -f "$HERE/SKILL.md" "$DEST/SKILL.md"
log "skill -> $DEST"

# --- 2. the VS Code theme pack ----------------------------------------------
# The pack MUST be installed through code-server's own CLI (`--install-extension
# <vsix>`) and NOT by copying the folder into extensions/. A copied folder is
# absent from extensions/extensions.json, and code-server PRUNES unregistered
# folders on its next launch: the pack silently vanishes and the theme picker
# shows no "Adom ..." entries at all, so a settings.json asking for "Adom Studio"
# falls back to stock Light. That bug shipped in a golden image; see SKILL.md
# "Delivering the VS Code pack". Do not "simplify" this back into a cp -r.
PACK_VERSION="$(python3 -c "import json;print(json.load(open('$HERE/vscode/package.json'))['version'])" 2>/dev/null || echo unknown)"
EXT_DIR="$HOME/.local/share/code-server/extensions"
EXT_ID="adom.adom-theme"
# legacy id from before the 2026-08-02 rename; always purge so the picker never doubles up
LEGACY_EXT_ID="adom.adom-themes"

# The `code-server` on PATH inside an editor terminal is the remote-cli shim; it
# cannot install extensions. Resolve the real launcher instead.
find_code_server() {
    local c
    for c in /usr/lib/code-server/bin/code-server \
             /usr/local/lib/code-server/bin/code-server \
             "$HOME/.local/lib/code-server/bin/code-server"; do
        [ -x "$c" ] && { printf '%s\n' "$c"; return 0; }
    done
    c="$(command -v code-server 2>/dev/null || true)"
    case "$c" in
        ""|*remote-cli*) return 1 ;;
        *) printf '%s\n' "$c" ;;
    esac
}

# code-server's CLI refuses to run ("error not spawned with IPC") when it inherits
# CODE_SERVER_PARENT_PID / VSCODE_IPC_HOOK_CLI from the editor terminal that is
# running this installer. Strip them.
run_code_server() {
    env -u CODE_SERVER_PARENT_PID -u VSCODE_IPC_HOOK_CLI "$@"
}

install_theme_pack() {
    local cs vsix
    cs="$(find_code_server)" || {
        log "no code-server launcher found; skipped the editor theme pack"
        return 0
    }
    command -v python3 >/dev/null 2>&1 || {
        log "python3 not available to package the pack; skipped the editor theme pack"
        return 0
    }

    vsix="$(mktemp /tmp/adom-themes-XXXXXX.vsix)"
    python3 - "$HERE/vscode" "$vsix" <<'PYEOF'
import sys, os, json, zipfile
src, out = sys.argv[1], sys.argv[2]
m = json.load(open(os.path.join(src, "package.json")))
pub, name, ver = m["publisher"], m["name"], m["version"]
esc = lambda s: (s.replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;"))
manifest = f'''<?xml version="1.0" encoding="utf-8"?>
<PackageManifest Version="2.0.0" xmlns="http://schemas.microsoft.com/developer/vsx-schema/2011">
  <Metadata>
    <Identity Language="en-US" Id="{name}" Version="{ver}" Publisher="{pub}" />
    <DisplayName>{esc(m.get("displayName", name))}</DisplayName>
    <Description xml:space="preserve">{esc(m.get("description", ""))}</Description>
    <Categories>Themes</Categories>
    <Properties>
      <Property Id="Microsoft.VisualStudio.Code.Engine" Value="{m.get("engines", {}).get("vscode", "^1.70.0")}" />
      <Property Id="Microsoft.VisualStudio.Code.ExtensionDependencies" Value="" />
      <Property Id="Microsoft.VisualStudio.Code.ExtensionPack" Value="" />
    </Properties>
  </Metadata>
  <Installation><InstallationTarget Id="Microsoft.VisualStudio.Code" /></Installation>
  <Dependencies />
  <Assets>
    <Asset Type="Microsoft.VisualStudio.Code.Manifest" Path="extension/package.json" Addressable="true" />
  </Assets>
</PackageManifest>
'''
content_types = '''<?xml version="1.0" encoding="utf-8"?>
<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
  <Default Extension="json" ContentType="application/json" />
  <Default Extension="vsixmanifest" ContentType="text/xml" />
  <Default Extension="md" ContentType="text/markdown" />
  <Default Extension="png" ContentType="image/png" />
</Types>
'''
with zipfile.ZipFile(out, "w", zipfile.ZIP_DEFLATED) as z:
    z.writestr("extension.vsixmanifest", manifest)
    z.writestr("[Content_Types].xml", content_types)
    for root, _, files in os.walk(src):
        for f in files:
            p = os.path.join(root, f)
            z.write(p, "extension/" + os.path.relpath(p, src).replace(os.sep, "/"))
PYEOF

    mkdir -p "$EXT_DIR"
    # Uninstall first so a stale entry is dropped from extensions.json too; a bare
    # `rm -rf` of the folder would leave the registration behind and dangling.
    run_code_server "$cs" --extensions-dir "$EXT_DIR" \
        --uninstall-extension "$EXT_ID" >/dev/null 2>&1 || true
    run_code_server "$cs" --extensions-dir "$EXT_DIR" \
        --uninstall-extension "$LEGACY_EXT_ID" >/dev/null 2>&1 || true
    if run_code_server "$cs" --extensions-dir "$EXT_DIR" \
        --install-extension "$vsix" --force >/dev/null 2>&1; then
        log "VS Code theme pack v$PACK_VERSION installed via code-server -> $EXT_ID"
    else
        log "WARNING: code-server refused the theme pack vsix; the editor will show no Adom themes"
        rm -f "$vsix"
        return 0
    fi
    rm -f "$vsix"

    # Registration is the whole point of this section -- assert it, loudly.
    if python3 - "$EXT_DIR/extensions.json" "$EXT_ID" <<'PYEOF'
import sys, json
try:
    entries = json.load(open(sys.argv[1]))
except Exception:
    sys.exit(1)
sys.exit(0 if any(e.get("identifier", {}).get("id") == sys.argv[2] for e in entries) else 1)
PYEOF
    then
        log "  registered in extensions.json (survives the next editor launch)"
        log "  (five 'Adom ...' themes appear in the theme picker after the editor reloads)"
    else
        log "WARNING: $EXT_ID is NOT in extensions.json -- code-server will prune the pack"
    fi
}

if [ -d "$HERE/vscode/themes" ]; then
    install_theme_pack
fi

# --- 3a. the OFL fonts (bundled) ----------------------------------------------
FONT_DEST="$HOME/.local/share/fonts/adom-theme"
if [ -d "$HERE/fonts" ]; then
    mkdir -p "$FONT_DEST"
    cp -f "$HERE"/fonts/jetbrains-mono/*.woff2 "$FONT_DEST/" 2>/dev/null || true
    cp -f "$HERE"/fonts/familjen-grotesk/*.woff2 "$FONT_DEST/" 2>/dev/null || true
    cp -f "$HERE"/fonts/jetbrains-mono/OFL.txt "$FONT_DEST/JetBrainsMono-OFL.txt" 2>/dev/null || true
    cp -f "$HERE"/fonts/familjen-grotesk/OFL.txt "$FONT_DEST/FamiljenGrotesk-OFL.txt" 2>/dev/null || true
    log "OFL fonts (JetBrains Mono, Familjen Grotesk) -> $FONT_DEST"
fi

# --- 3b. Satoshi (fetched from Fontshare's official servers) -------------------
# Skipped silently when offline or already present; the theme's prose stacks all
# carry system fallbacks, so nothing breaks without it.
SATOSHI_URL="https://api.fontshare.com/v2/fonts/download/satoshi"
if [ "${ADOM_THEME_SKIP_SATOSHI:-0}" = "1" ]; then
    # Image bakes and other PUBLIC artifacts must not carry Satoshi (Fontshare EULA
    # forbids public redistribution). Set ADOM_THEME_SKIP_SATOSHI=1 and let each
    # machine fetch it at first setup. See fonts/LICENSES.md.
    log "Satoshi fetch SKIPPED (ADOM_THEME_SKIP_SATOSHI=1) - fetch per-machine at setup"
elif [ -f "$FONT_DEST/Satoshi-Regular.woff2" ]; then
    log "Satoshi already present -> $FONT_DEST"
elif command -v curl >/dev/null 2>&1 && command -v python3 >/dev/null 2>&1; then
    TMPZ="$(mktemp /tmp/satoshi-XXXXXX.zip)"
    if curl -fsSL --compressed -A "Mozilla/5.0" -o "$TMPZ" "$SATOSHI_URL" 2>/dev/null; then
        python3 - "$TMPZ" "$FONT_DEST" <<'PYEOF'
import sys, zipfile, os
zpath, dest = sys.argv[1], sys.argv[2]
WANT = ['Satoshi-Regular.woff2','Satoshi-Medium.woff2','Satoshi-Bold.woff2','Satoshi-Variable.woff2']
got = 0
with zipfile.ZipFile(zpath) as z:
    for name in z.namelist():
        base = os.path.basename(name)
        if base in WANT and '/WEB/' in name:
            data = z.read(name)
            if data[:4] != b'wOF2':
                print(f"[adom-theme]   {base}: not wOF2, skipped"); continue
            open(os.path.join(dest, base),'wb').write(data)
            got += 1
print(f"[adom-theme] Satoshi: {got}/{len(WANT)} faces from Fontshare (official servers, per its EULA)")
sys.exit(0 if got else 1)
PYEOF
        rm -f "$TMPZ"
    else
        rm -f "$TMPZ"
        log "Satoshi fetch skipped (offline?) - get it later: see fonts/satoshi/README.md on the page"
    fi
else
    log "Satoshi fetch skipped (needs curl+python3) - see fonts/satoshi/README.md on the page"
fi
command -v fc-cache >/dev/null 2>&1 && fc-cache -f "$FONT_DEST" >/dev/null 2>&1 || true

log "done"
