#!/usr/bin/env python3
"""Generate a MediaWiki Items page from the authoritative item registry.

Source = items_registry.json, built from CheatItemDefinitionsData.Items
(List<ItemDefinition>). An entry exists iff the game defines it as a carriable
item (it has an ItemDefinition / StorageStack). Damage-type name variants
(_Ranged/_Melee) and world objects are NOT in this list, by design.
"""
import json, os

EX = '/home/downloadpizza/sand_tools/extracted'
WIKI = '/home/downloadpizza/sand_tools/wiki'
OUT = os.path.join(WIKI, 'Items.mediawiki')

reg = json.load(open(os.path.join(EX, 'items_registry.json')))['items']

CAT_LABEL = {
    'WEAPON': 'Weapon', 'AMMO': 'Ammo', 'TURRET_AMMO': 'Turret Ammo',
    'RESOURCE_T1': 'Resource (T1)', 'RESOURCE_T2': 'Resource (T2)', 'RESOURCE_T3': 'Resource (T3)',
    'ARMOR': 'Armor', 'BACKPACK': 'Backpack', 'ENERGY': 'Energy', 'FOOD': 'Food', 'MONEY': 'Money',
    'KEY': 'Key', 'SMALL_VALUABLE': 'Small Valuable', 'LARGE_VALUABLE': 'Large Valuable',
    'RAID_EXPLOSIVES': 'Raid Explosive', 'WEAPON_BELT': 'Weapon Belt',
    'UTILITY_CONSUMABLE': 'Utility Consumable', 'ATTACK_CONSUMABLE': 'Attack Consumable',
}

def esc(s):
    return (s or '').replace('\n', ' ').replace('|', '&#124;').strip()

def stack(n):
    return '—' if n >= 100000 else str(n)   # 100000/1000000 = effectively unlimited

def main():
    out = []
    out.append("Complete list of carriable '''items''' in '''SAND''' — everything the game defines as an "
               "actual inventory item (i.e. it has an item definition). Names and descriptions are the "
               "in-game English text.")
    out.append('')
    out.append(f"{len(reg)} items. The table is sortable — click a header to group by category. "
               "(Damage-type name variants and world objects are intentionally excluded; this is the "
               "real pickup-able item set.)")
    out.append('')
    out.append('__TOC__')
    out.append('')
    out.append('== Items ==')
    out.append('{| class="wikitable sortable"')
    out.append('! Category !! Name !! Item ID !! data-sort-type="number" | Stack !! Short description')
    rows = sorted(reg.items(), key=lambda kv: (kv[1]['type'], kv[1]['name'].lower()))
    for iid, info in rows:
        cat = CAT_LABEL.get(info['type'], info['type'].title())
        out.append('|-')
        out.append(f"| {cat} || [[{info['name']}]] || <code>{iid}</code> "
                   f"|| {stack(info['storageStack'])} || {esc(info['shortDescription'])}")
    out.append('|}')
    out.append('')
    out.append('== Notes ==')
    out.append('* The item set comes from the game\'s item-definition registry '
               '(<code>CheatItemDefinitionsData.Items</code>): an entry is included only if the game '
               'defines it as a carriable item. This deliberately excludes damage-type name variants '
               '(<code>_Ranged</code>/<code>_Melee</code>) and world objects, which merely have '
               'display names but are not inventory items.')
    out.append('* "Stack" is the item\'s storage stack limit; "—" means effectively unlimited.')
    out.append('* Full long-form descriptions exist for most items and can be added per page.')
    out.append('')
    out.append('[[Category:Items]]')
    text = '\n'.join(out)
    os.makedirs(WIKI, exist_ok=True)
    open(OUT, 'w').write(text)
    from collections import Counter
    c = Counter(CAT_LABEL.get(v['type'], v['type']) for v in reg.values())
    print(f"wrote {OUT} ({len(text)} chars, {len(reg)} items)")
    for k, v in c.most_common():
        print(f"  {v:3d}  {k}")

if __name__ == '__main__':
    main()
