#!/usr/bin/env python3
"""Build one scheduler bootlet that preloads the distinct CLUTs required by several fixture tags.

Usage: gs_merge_scheduler_bootlets.py <output-tag> <input-tag> [<input-tag> ...]
"""
import os
import re
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, DATA)
import bake

RAM_QWORDS = 512
HEADER_QWORDS = 16
FBW = 10
FBPXW = 640
FBH = 480


def read_payload(tag):
    path = os.path.join(DATA, f"payload_sh3_{tag}.mem")
    with open(path) as f:
        lines = f.readlines()
    header = next((line for line in lines if line.startswith("//")), "")
    match = re.search(r"QWC=(\d+)", header)
    if not match:
        raise ValueError(f"{path}: missing QWC metadata")
    cbp_match = re.search(r"CBPs \[([^]]*)\]", header)
    if not cbp_match:
        raise ValueError(f"{path}: missing CBP metadata")
    cbps = [int(x.strip()) for x in cbp_match.group(1).split(",") if x.strip()]
    words = [int(line.strip(), 16) for line in lines if line.strip() and not line.startswith("//")]
    if len(words) != RAM_QWORDS:
        raise ValueError(f"{path}: expected {RAM_QWORDS} qwords, got {len(words)}")
    qwc = int(match.group(1))
    if qwc > RAM_QWORDS - HEADER_QWORDS:
        raise ValueError(f"{path}: QWC {qwc} exceeds payload capacity")
    return qwc, cbps, words[HEADER_QWORDS:HEADER_QWORDS + qwc]


def main(argv):
    if len(argv) < 4:
        print(__doc__.strip())
        return 2
    output_tag, input_tags = argv[1], argv[2:]
    active = []
    seen_cbps = set()
    for tag in input_tags:
        qwc, cbps, words = read_payload(tag)
        for cbp in set(cbps):
            if cbp in seen_cbps:
                raise ValueError(f"duplicate relocated CBP {cbp}: fixture {tag} aliases an earlier input")
            seen_cbps.add(cbp)
        if len(words) != qwc:
            raise ValueError(f"payload word count mismatch for {tag}")
        active.extend(words)
    if len(active) > RAM_QWORDS - HEADER_QWORDS:
        raise ValueError(f"combined QWC {len(active)} exceeds {RAM_QWORDS - HEADER_QWORDS}")

    payload_name = f"payload_sh3_{output_tag}.mem"
    bios_name = f"bios_sh3_{output_tag}.mem"
    with open(os.path.join(DATA, payload_name), "w") as f:
        f.write(f"// combined scheduler CLUT preload tags={input_tags} CBPs={sorted(seen_cbps)} QWC={len(active)}. gitignored.\n")
        for _ in range(HEADER_QWORDS):
            f.write("00000000000000000000000000000000\n")
        for word in active:
            f.write(f"{word:032x}\n")
        for _ in range(RAM_QWORDS - HEADER_QWORDS - len(active)):
            f.write("00000000000000000000000000000000\n")
    display1_hi = ((FBH - 1) << 12) | (FBPXW - 1)
    bake.write_bios_mem(
        bios_name,
        bake.build_textured_demo_bootlet_disp(len(active), display1_hi, FBW),
        f"combined scheduler CLUT preload tags={input_tags} QWC={len(active)} DISPLAY1={FBPXW}x{FBH}. gitignored.",
    )
    print(f"[bootlet] emitted {bios_name} + {payload_name}: QWC={len(active)} CBPs={sorted(seen_cbps)}")
    return 0


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