#!/usr/bin/env python3
"""Score the feeder-derived fixed-point ZSCHED model with the TB oracle rule."""
import contextlib
import io
import os
import sys

HERE = os.path.dirname(os.path.abspath(__file__))
ROOT = os.path.normpath(os.path.join(HERE, ".."))
DATA = os.path.join(ROOT, "sim", "data", "top_psmct32_raster_demo")
sys.path.insert(0, HERE)

with contextlib.redirect_stdout(io.StringIO()):
    import diagnose_zsched_persp as D


def load_mem(path):
    out = []
    with open(path) as f:
        for line in f:
            s = line.strip()
            if s and not s.startswith("//"):
                out.append(int(s, 16) & 0xFFFFFFFF)
    return out


def cell(idx_words, pal, u, v):
    if not (0 <= u < D.TW and 0 <= v < D.TH):
        return None
    lin = v * D.TW + u
    ci = (idx_words[lin // 4] >> (8 * (lin % 4))) & 0xFF
    return pal[ci] & 0xFFFFFF


def main(argv):
    tag = argv[1] if len(argv) > 1 else "zsched"
    with contextlib.redirect_stdout(io.StringIO()):
        draw_idxs, _tris, fb, _owner, _emitted, _accepted, _frags = D.render(tag)

    idx = [load_mem(os.path.join(DATA, f"sh3_{tag}{e}_idx.mem")) for e in range(len(draw_idxs))]
    pal = [load_mem(os.path.join(DATA, f"sh3_{tag}{e}_pal.mem")) for e in range(len(draw_idxs))]
    refmap = load_mem(os.path.join(DATA, f"sh3_{tag}_refmap.mem"))
    ref_ep = [load_mem(os.path.join(DATA, f"sh3_{tag}{e}_refmap.mem")) for e in range(len(draw_idxs))]

    all_tot = all_ok = multi_tot = multi_ok = clut_bad = 0
    for o, rw in enumerate(refmap):
        if not (rw >> 31):
            continue
        fbc = fb[o] & 0xFFFFFF
        all_tot += 1
        matched = False
        for e in range(len(draw_idxs)):
            ew = ref_ep[e][o]
            if not (ew >> 31):
                continue
            tu = (ew >> 9) & 0x1FF
            tv = ew & 0x1FF
            for rad in range(2):
                for du in range(-rad, rad + 1):
                    for dv in range(-rad, rad + 1):
                        if max(abs(du), abs(dv)) != rad:
                            continue
                        if cell(idx[e], pal[e], tu + du, tv + dv) == fbc:
                            matched = True
        if matched:
            all_ok += 1
        if rw & (1 << 28):
            multi_tot += 1
            if matched:
                multi_ok += 1
        if fbc != 0:
            in_pal = any((p & 0xFFFFFF) == fbc for pp in pal for p in pp)
            if not in_pal:
                clut_bad += 1

    all_pct = 100.0 * all_ok / all_tot if all_tot else 0.0
    multi_pct = 100.0 * multi_ok / multi_tot if multi_tot else 0.0
    print(f"[model-oracle] tag={tag} ALL={all_ok}/{all_tot} ({all_pct:.2f}%) "
          f"MULTI={multi_ok}/{multi_tot} ({multi_pct:.2f}%) clut_bad={clut_bad}")
    return 0


if __name__ == "__main__":
    raise SystemExit(main(sys.argv))
