"""DIMENSION 2 batch 1: what happens to cards after the reveal.

HYPOTHESES
 H1 duplicateItemIdList (atom 0xec) in createPackResponse (deser 0x180162880)
    lands in a store offset that some UI/flow code reads. Find the offset, then
    find every reader.
 H2 Quick Sell == "Discard" in this codebase (strings CardsDiscardCard /
    CardsDiscardCardList / CardsDiscardCardByRes, RS4:FutDiscardCardServerResponse).
    FutDiscardCard deser 0x180127300 parses items/totalCredits/id. Question is
    whether the coin credit is taken from totalCredits (server) or recomputed from
    the item's discardValue (client).
 H3 Send-to-transfer-list from the reveal reuses FutMoveCard (PUT ut/%s/item) with
    a pile change rather than a new endpoint.
 H4 CardsDiscardCardList is the bulk variant and is ONE request carrying a list.

CONTROLS (must resolve, else class_deser is misbehaving this run):
    FutSquadSave -> 0x180171a60, FutSquadList -> 0x180172140,
    FutCreateMatch -> 0x180120380
"""
import traceback, os

OUT = "/tmp/claude-1000/-home-alex-Documents-OpenFUT/8e521ca1-ca3e-4138-bb96-df1744dd1d30/scratchpad/packres"


def dump(name, text):
    p = os.path.join(OUT, name)
    with open(p, "w") as f:
        f.write(text)
    print("[wrote %s  %d chars]" % (p, len(text)))


try:
    print("=" * 78)
    print("SECTION 0 -- class_deser CONTROLS")
    for c in ("FutSquadSave", "FutSquadList", "FutCreateMatch"):
        print(" ", c, [hex(x[0]) for x in class_deser(c)])

    print("=" * 78)
    print("SECTION 0b -- class_deser TARGETS")
    for c in ("FutDiscardCardServerResponse", "FutDiscardCardByResServerResponse",
              "FutMoveCardServerResponse", "FutMoveCardByResServerResponse",
              "FutSwapCardServerResponse", "FutCreatePackServerResponse",
              "FutISStartServerResponse"):
        print(" ", c, [hex(x[0]) for x in class_deser(c)])

    print("=" * 78)
    print("SECTION 1 -- createPackResponse deserializer 0x180162880 FULL")
    s = dec(0x180162880)
    print("len(src) =", len(s))
    print(s)
    dump("d2_createpack_deser.txt", s)

    print("=" * 78)
    print("SECTION 2 -- nested int-list parser 0x180138e10 FULL "
          "(duplicateItemIdList element parser per ENDPOINT_MAP)")
    s = dec(0x180138E10)
    print("len(src) =", len(s))
    print(s)
    dump("d2_138e10_intlist.txt", s)

    print("=" * 78)
    print("SECTION 3 -- FutDiscardCard deser 0x180127300 FULL")
    s = dec(0x180127300)
    print("len(src) =", len(s))
    print(s)
    dump("d2_discardcard_deser.txt", s)

    print("=" * 78)
    print("SECTION 3b -- FutDiscardCardByRes deser 0x1801279c0 FULL")
    s = dec(0x1801279C0)
    print("len(src) =", len(s))
    print(s)
    dump("d2_discardcardbyres_deser.txt", s)

    print("=" * 78)
    print("SECTION 4 -- string xrefs for the action names")
    names = {
        "CardsDiscardCard": 0x1801EF6C5,
        "CardsDiscardCardList": 0x1801EF6DD,
        "CardsDiscardCardByRes": 0x1801EF6F5,
        "DiscardCard": 0x18021EEA8,
        "DISCARDCARD": 0x18021EEB8,
        "DiscardCardByRes": 0x18021EEC8,
        "DiscardACard": 0x18021EEF8,
        "DISCARDACARD": 0x18021EF08,
        "MoveCard": 0x18021EF18,
        "MOVECARD": 0x18021EF28,
        "SwapCard": 0x18021EF58,
        "CardsSwapCards": 0x1801EF6B5,
        "GetCardDuplicate": 0x1801F3ADF,
        "TO_TRADEPILE": 0x1802391A8,
        "Tradepile": 0x18021CF08,
        "tradepile_lc": 0x18022FB20,
        "tradePile_cc": 0x18022FB30,
        "discardValue_key": 0x180230BE8,
        "duplicateItemId": 0x180230D08,
        "duplicateItemIdList": 0x180230D18,
        "duplicateItemLoans": 0x180230D30,
        "fcc_discardcoins": 0x1802231F4,
        "swap_key": 0x18022F7EC,
        "swapPlayerDefIds": 0x18022F7F8,
        "AddCardBackToTradePile": 0x1801F3C15,
        "RemoveFromTradePile": 0x1801EFADA,
        "RemoveAllSoldFromTradePile": 0x1801EFAF9,
    }
    for n, va in sorted(names.items()):
        got = rd_str(va, 60)
        # the -4 rule may apply to some; report the literal we actually see
        xs = xrefs_to(va)
        print("%-28s %#x  str=%r  xrefs=%d" % (n, va, got, len(xs)))
        for frm, typ, fn, ent in xs[:12]:
            print("      from %#x %s in %s (%#x)" % (frm, typ, fn, ent))

    print("=" * 78)
    print("SECTION 5 -- where is atom 0xd7 discardValue handled? "
          "search .text for the immediate 0xd7 near the item deser")
    print("item element deser 0x18013fe00:")
    s = dec(0x18013FE00)
    print("len(src) =", len(s))
    dump("d2_item_elem_deser.txt", s)
    print(s[:6000])
    print("... [full copy written to d2_item_elem_deser.txt]")

except Exception:
    traceback.print_exc()
