"""Q15: find the equip path by the atoms it must name.

The itemState vocabulary is also in the atom table:
    0xc activeAwayKit  0xd activeBadge  0xe activeBall  0x10 activeHomeKit
    0x12 activeStadium  0xa active  0x12e free  0x164 inGame  0x1e5 offered
and the club ?type= taxonomy switch FUN_18012ec50 shows how a name reaches the wire:
FUN_180180cd0(atom) returns the atom's name string. So whatever chooses which of the
five active* states to send must call FUN_180180cd0 with 0xc/0xd/0xe/0x10/0x12, and
the choice is made from the item's family. That is the mapping the brief wants.

Method: enumerate every caller of FUN_180180cd0, decompile each once, and report the
call sites whose literal argument is one of the atoms of interest:
   equip states  0xc 0xd 0xe 0x10 0x12
   club families 0x49 badge, 0x179 kit, 0x2d8 stadium, 0x4d ball,
                 0x18d leaguelogos, 0x10a equippables, 0x4b badges, 0x4f balls,
                 0x17c kits, 0x18e leagueLogos, 0x2d7 stadia
Print the matching lines with context so the surrounding switch is visible.

CONTROL: FUN_18012ec50 is a known caller and must be reported with its family atoms
(0x49, 0x179, 0x2d8, 0x4d, 0x18d, 0x10a). If it is not in the output, the caller
enumeration or the literal matching is broken.
"""
import re
import traceback

WANT = {0xC: "activeAwayKit", 0xD: "activeBadge", 0xE: "activeBall",
        0x10: "activeHomeKit", 0x12: "activeStadium", 0xA: "active",
        0x12E: "free", 0x164: "inGame", 0x1E5: "offered",
        0x49: "badge", 0x179: "kit", 0x2D8: "stadium", 0x4D: "ball",
        0x18D: "leaguelogos", 0x10A: "equippables", 0x4B: "badges",
        0x4F: "balls", 0x17C: "kits", 0x18E: "leagueLogos", 0x2D7: "stadia"}

try:
    ents = {}
    for frm, typ, fn, ent in xrefs_to(0x180180CD0):
        if ent:
            ents[ent] = fn
    print("callers of FUN_180180cd0: %d" % len(ents))
    pat = re.compile(r"FUN_180180cd0\((0x[0-9a-f]+|\d+)\)")
    nhit = 0
    for ent, fn in sorted(ents.items()):
        src = dec(ent)
        lines = src.splitlines()
        found = []
        for i, l in enumerate(lines):
            for m in pat.finditer(l):
                v = int(m.group(1), 0)
                if v in WANT:
                    found.append((i, v))
        if not found:
            continue
        nhit += 1
        print("=" * 70)
        print("%s @%#x len=%d  atoms=%s" %
              (fn, ent, len(src),
               sorted({"%#x=%s" % (v, WANT[v]) for _i, v in found})))
        shown = set()
        for i, _v in found:
            for j in range(max(0, i - 4), min(len(lines), i + 2)):
                if j in shown:
                    continue
                shown.add(j)
                print("   %4d: %s" % (j, lines[j].strip()))
            print("   ---")
    print("functions with hits: %d" % nhit)
except Exception:
    traceback.print_exc()
