"""q_cd_route_3 -- the ?type= vocabulary itself, and the remaining club value maps.

HYPOTHESIS
  FUN_18012ddf0 (the ClubSearch / FutStickerBookSearch query builder, decompiled in
  q_cd_route_2) writes the type= parameter from FUN_18012ec50(code), where code is
  *(req+0x10) after a 3-case remap of *(req+0x14).  FUN_18012ec50 is therefore the
  COMPLETE code->string map for club?type=, and enumerating its cases (switch labels
  AND == AND != AND any sub/dec ladder, read from a full-length decompile) closes the
  vocabulary.  The one branch that bypasses it is code 0xf, which picks
  badge/kit/stadium/ball/equippables from *(req+0x30).

CONTROLS
  * FUN_18012ec50 is decompiled alongside three sibling value maps used by the same
    builder for other parameters -- FUN_1800d8b50 (position=), FUN_180166620
    (formation=), FUN_18012ee20 (state=).  If FUN_18012ec50 came back as a stub while
    those three came back as real tables, the stub is a fact; if all four are stubs
    the method is at fault.
  * Both enum reverse-lookups over the two candidate tables are re-printed with their
    callers, so "table 0x180229c30 is/is not the type= vocabulary" is decided by a
    caller edge and not by the table's contents looking plausible.
  * len(src) is printed for every function and every body is printed in full, so no
    absence claim here rests on a truncated decompile.
"""
import traceback

try:
    def show(label, ea):
        f = fm.getFunctionContaining(addr(ea)) if ea else None
        print("=" * 78)
        print("### %s  @ %s  -> %s" % (label, hex(ea), f.getName() if f else "NO FUNC"))
        if f is None:
            return
        print("    entry %s  body %s" % (f.getEntryPoint(), f.getBody()))
        src = dec(f)
        print("    len(src) = %d" % len(src))
        print(src)
        try:
            cs = sorted(set(int(x.getEntryPoint().getOffset())
                            for x in f.getCallingFunctions(mon)))
            print("    callers: %s" % ", ".join(hex(c) for c in cs))
        except Exception as e:
            print("    callers: <%s>" % e)

    show("type= value map FUN_18012ec50", 0x18012ec50)
    show("position= value map FUN_1800d8b50", 0x1800d8b50)
    show("formation= value map FUN_180166620", 0x180166620)
    show("state= value map FUN_18012ee20", 0x18012ee20)
    show("enum revlookup 0x180229ab0", 0x180166300)
    show("enum revlookup 0x180229c30", 0x180166340)
except Exception:
    traceback.print_exc()
