#!/usr/bin/env python3
"""Detect the Altium Designer install + library locations on this Windows machine.

Runs INSIDE the user's desktop (the bridge is spawned by Adom Desktop on Windows),
so it reads the registry and filesystem directly — no relay/shell round-trip.

Verified facts on the reference machine (BARRETTLAND / user barre):
  - Install:  C:\\Program Files\\Altium\\AD26\\X2.exe
  - Uninstall key: HKLM\\...\\Uninstall\\Altium Designer {GUID}  (DisplayName "Altium Designer 26",
                   InstallLocation, DisplayIcon → X2.exe)
  - Config:   %LOCALAPPDATA%\\Altium\\Altium Designer {GUID}  and  %APPDATA%\\Altium\\...
  - Data:     C:\\Users\\Public\\Documents\\Altium\\AD26\\{Library,OutputJobs,Templates,Examples}
"""

import os
import glob

try:
    import winreg  # type: ignore
except ImportError:  # non-Windows (dev/import only)
    winreg = None

UNINSTALL_PATHS = [
    r"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall",
    r"SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall",
]


def _reg_altium_uninstall():
    """Walk the Uninstall keys for an entry whose DisplayName starts with 'Altium Designer'.

    Returns dict {display_name, display_version, install_location, display_icon} or None.
    """
    if winreg is None:
        return None
    for base in UNINSTALL_PATHS:
        try:
            root = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, base)
        except OSError:
            continue
        i = 0
        while True:
            try:
                sub = winreg.EnumKey(root, i)
            except OSError:
                break
            i += 1
            if "Altium Designer" not in sub:
                continue
            try:
                k = winreg.OpenKey(root, sub)
            except OSError:
                continue

            def _get(name):
                try:
                    return winreg.QueryValueEx(k, name)[0]
                except OSError:
                    return None

            name = _get("DisplayName")
            if not name or not str(name).startswith("Altium Designer"):
                continue
            return {
                "display_name": name,
                "display_version": _get("DisplayVersion"),
                "install_location": _get("InstallLocation"),
                "display_icon": _get("DisplayIcon"),
            }
    return None


def _scan_program_files():
    """Fallback: find the newest C:\\Program Files\\Altium\\AD<NN>\\X2.exe."""
    candidates = []
    for pf in (os.environ.get("ProgramFiles", r"C:\Program Files"),
               os.environ.get("ProgramFiles(x86)", r"C:\Program Files (x86)")):
        for exe in glob.glob(os.path.join(pf, "Altium", "AD*", "X2.exe")):
            ad = os.path.basename(os.path.dirname(exe))  # e.g. AD26
            num = "".join(ch for ch in ad if ch.isdigit())
            candidates.append((int(num or 0), ad, exe))
    candidates.sort(reverse=True)
    return candidates[0] if candidates else None


def _config_dirs():
    """Find the Altium config dirs (carry the {GUID} and any Workspace/365 state)."""
    out = []
    for env in ("LOCALAPPDATA", "APPDATA"):
        base = os.path.join(os.environ.get(env, ""), "Altium")
        if os.path.isdir(base):
            for d in os.listdir(base):
                if d.startswith("Altium Designer"):
                    out.append(os.path.join(base, d))
    return out


def detect_altium():
    """Return a structured snapshot of the Altium install on this machine.

    {installed, exe, version, install_location, config_dirs[], data_dir,
     library_dir, outputjobs_dir}
    """
    reg = _reg_altium_uninstall()
    exe = None
    install_location = None
    version = None

    if reg:
        version = reg.get("display_version") or reg.get("display_name")
        install_location = reg.get("install_location")
        icon = reg.get("display_icon")
        if icon and icon.lower().endswith("x2.exe") and os.path.isfile(icon):
            exe = icon
        elif install_location:
            cand = os.path.join(install_location, "X2.exe")
            if os.path.isfile(cand):
                exe = cand

    if not exe:
        scanned = _scan_program_files()
        if scanned:
            _, ad, exe = scanned
            install_location = os.path.dirname(exe)
            version = version or ad

    # Public data tree — derive AD<NN> from the install dir name when possible.
    ad_name = os.path.basename(install_location) if install_location else "AD26"
    public = os.path.join(
        os.environ.get("PUBLIC", r"C:\Users\Public"), "Documents", "Altium", ad_name
    )
    data_dir = public if os.path.isdir(public) else None
    library_dir = os.path.join(public, "Library") if data_dir else None
    outputjobs_dir = os.path.join(public, "OutputJobs") if data_dir else None

    return {
        "installed": bool(exe),
        "exe": exe,
        "version": version,
        "install_location": install_location,
        "config_dirs": _config_dirs(),
        "data_dir": data_dir,
        "library_dir": library_dir,
        "outputjobs_dir": outputjobs_dir,
    }


if __name__ == "__main__":
    import json
    print(json.dumps(detect_altium(), indent=2))
