import json, os, shutil, subprocess, time, threading

ROOT="/Users/oscar/.worktree/hot-reload/labs/hot-reload"
REC=f"{ROOT}/target/kan-hot/debug/rustc"
SCRATCH="/private/var/folders/ft/fkt3bwqd01g7f54wvyz9wgjc0000gn/T/opencode/pipe/out2"
def load(n): return json.load(open(f"{REC}/{n}.json"))
def env_of(d, extra=None):
    e=dict(d["env"]); e["PATH"]=os.environ["PATH"]
    if extra: e.update(extra)
    return e
def run(argv, d, env, outdir=None):
    argv=list(argv)
    if outdir:
        i=argv.index("--out-dir"); argv[i+1]=outdir
    t=time.monotonic(); p=subprocess.run(argv,cwd=d["cwd"],env=env,capture_output=True,text=True)
    return (time.monotonic()-t)*1000,p

common=load("api_common"); api=load("api")
shutil.rmtree(SCRATCH,ignore_errors=True); os.makedirs(SCRATCH)

def api_with(rmeta, incname, runs=2, extra_env=None):
    inc=f"{SCRATCH}/{incname}"; shutil.rmtree(inc,ignore_errors=True)
    out=[]
    j=0
    while j<len(api["argv"]):
        a=api["argv"][j]
        if a.startswith("--extern=api_common="):
            out.append(f"--extern=api_common={rmeta}")
        elif a=="-C" and j+1<len(api["argv"]) and api["argv"][j+1].startswith("incremental="):
            out+=["-C",f"incremental={inc}"]; j+=1
        else: out.append(a)
        j+=1
    # out-dir scratch
    i=out.index("--out-dir"); out[i+1]=SCRATCH
    res=[]
    for r in range(runs):
        t=time.monotonic(); p=subprocess.run(out,cwd=api["cwd"],env=env_of(api,extra_env),capture_output=True,text=True)
        res.append(((time.monotonic()-t)*1000,p))
    return res

# full compile reference
dt,p=run(common["argv"],common,env_of(common),SCRATCH)
rf=[f for f in os.listdir(SCRATCH) if f.endswith('.rmeta')][0]
rlibf=[f for f in os.listdir(SCRATCH) if f.endswith('.rlib')][0]
print(f"full api-common {dt:.1f}ms rc={p.returncode}")
r=api_with(os.path.join(SCRATCH,rf),"inc_full")
print("api vs full-rmeta", [f"{x:.1f}rc{y.returncode}" for x,y in r])

# meta-only with always-encode-mir
argv=list(common["argv"]); i=argv.index("--emit=dep-info,metadata,link"); argv[i]="--emit=metadata"; argv.append("-Zalways-encode-mir")
dt,p=run(argv,common,env_of(common,{"RUSTC_BOOTSTRAP":"1"}),SCRATCH)
rm=[f for f in os.listdir(SCRATCH) if f.endswith('.rmeta')][0]
print(f"meta-only+mir {dt:.1f}ms rc={p.returncode}")
r=api_with(os.path.join(SCRATCH,rm),"inc_mir")
print("api vs mir-rmeta", [f"{x:.1f}rc{y.returncode}" for x,y in r])
