import json, os, shutil, subprocess, time, glob
ROOT="/Users/oscar/.worktree/hot-reload/labs/hot-reload"; REC=f"{ROOT}/target/kan-hot/debug/rustc"
DEPS=f"{ROOT}/target/debug/deps"; SRC=f"{ROOT}/api-common/src/lib.rs"; BASE="/private/var/folders/ft/fkt3bwqd01g7f54wvyz9wgjc0000gn/T/opencode/pipe/out26"
def load(n): return json.load(open(f"{REC}/{n}.json"))
def strip_owned(argv):
    out=[]; i=1
    while i<len(argv):
        a=argv[i]
        if a=="-C" and i+1<len(argv) and any(argv[i+1].startswith(p) for p in ("incremental=","codegen-units=","debuginfo=")): i+=2; continue
        if a.startswith("-C") and any(a[2:].startswith(p) for p in ("incremental=","codegen-units=","debuginfo=")): i+=1; continue
        out.append(a); i+=1
    return out
def rewrite_extern(argv,name,path):
    out=[]; i=0
    while i<len(argv):
        a=argv[i]
        if a=="--extern" and i+1<len(argv) and argv[i+1].startswith(name+"="):
            out+=["--extern",f"{name}={path}"]; i+=2; continue
        if a.startswith(f"--extern={name}="):
            out.append(f"--extern={name}={path}"); i+=1; continue
        out.append(a); i+=1
    return out
common=load("api_common"); api=load("api"); orig=open(SRC).read(); assert "nested-v1" in orig
shutil.rmtree(BASE,ignore_errors=True); os.makedirs(BASE)
def common_compile(outdir,mode,mark):
    open(SRC,"w").write(orig.replace("nested-v1",mark))
    ca=[common["argv"][0]]+strip_owned(common["argv"])+["-C","debuginfo=0","-C","codegen-units=1"]
    if mode.startswith("meta"):
        i=ca.index("--emit=dep-info,metadata,link"); ca[i]="--emit=metadata"
    j=ca.index("--out-dir"); ca[j+1]=outdir
    env=dict(common["env"])
    if "mir" in mode: env["RUSTC_BOOTSTRAP"]="1"; ca+=["-Zalways-encode-mir"]
    s=time.monotonic(); p=subprocess.run(ca,cwd=common["cwd"],env=env,stdout=subprocess.DEVNULL,stderr=subprocess.PIPE); return (time.monotonic()-s)*1000,p.returncode,p.stderr[:300]
def api_compile(outdir,name,mark,extra=()):
    rmeta=os.path.join(outdir,[f for f in os.listdir(outdir) if f.startswith("libapi_common") and f.endswith(".rmeta")][0])
    raw=rewrite_extern([api["argv"][0]]+strip_owned(api["argv"]),"api_common",rmeta)
    aa=raw+["-C","debuginfo=0","-C","codegen-units=8","-C",f"incremental={BASE}/inc/{name}"]+list(extra)
    j=aa.index("--out-dir"); aa[j+1]=outdir
    env=dict(api["env"]); env["RUSTC_BOOTSTRAP"]="1"
    s=time.monotonic(); p=subprocess.run(aa,cwd=api["cwd"],env=env,stdout=subprocess.DEVNULL,stderr=subprocess.PIPE); t=(time.monotonic()-s)*1000
    # find newest api rlib and check marker
    marker_ok=False
    for f in glob.glob(os.path.join(outdir,"libapi-*.rlib")):
        marker_ok = mark.encode() in open(f,"rb").read()
    errs=[l for l in p.stderr.decode(errors="replace").splitlines() if 'missing optimized' in l]
    return t,p.returncode,marker_ok,errs[:1]
def trial(label,common_mode,extra=()):
    d=f"{BASE}/{label}"; os.makedirs(d,exist_ok=True)
    for f in glob.glob(os.path.join(d,"*")): os.remove(f)
    ct,crc,cerr=common_compile(d,common_mode,f"e26-{label}")
    at,arc,mok,errs=api_compile(d,label,f"e26-{label}",extra)
    print(f"{label:20s} common={ct:.1f}/{crc} api={at:.1f}/{arc} marker={mok} err={errs}")
    if crc: print("  common err:",cerr[:200])
try:
    trial("full","full")
    trial("meta_plain","meta")
    trial("meta_mir","meta_mir")
    trial("meta_noinline","meta",["-Zinline-mir=no"])
    trial("meta_mir_noinline","meta_mir",["-Zinline-mir=no"])
    trial("full_noinline","full",["-Zinline-mir=no"])
finally:
    open(SRC,"w").write(orig)
