"""Native preseason-transfer data/engine builder; no live files are installed."""
from pathlib import Path
import struct,json
from allstar import catalogue
from transfer_model import Market,ORDER
ENTRY=0x234000
INITIAL=0x238000
PLAYERS=0x238800
PRICES=0x239500
POSITIONS=0x239B80
OVERALLS=0x239EC0
PHOTOS=0x23A200
CURRENCY=0x23AF00
CATALOGUE_CRC=0x23AF04
RANKS=0x23AF08
EMPTY=0x23B588
PHOTO_FLAGS=0x23B600
OVR_SORTED=0x23BA00

def install(data,patch,assemble):
 players=catalogue(data);market=Market(players)
 def put(at,blob):patch(at,b'\xff'*len(blob),bytes(blob))
 assert max(market.price(p['uid'])for p in players)<=9999, 'USD list field supports ten characters at scale1000'
 put(INITIAL,market.encode(market.initial(),1));put(PLAYERS,b''.join(struct.pack('>I',p['record'])for p in players));put(PRICES,b''.join(struct.pack('>H',market.price(p['uid']))for p in players));put(POSITIONS,bytes(ORDER[p['position']]if p['uid']in market.allowed else 255 for p in players));put(OVERALLS,bytes(p['overall']for p in players));photos=[]
 photo_flags=[]
 for p in players:
  old=struct.unpack_from('>I',data,0x38e+4*p['team'])[0];matches=[j for j in range(26)if struct.unpack_from('>H',data,old+6*j+4)[0]==p['slot']];assert len(matches)==1;photos.append(struct.unpack_from('>I',data,old+6*matches[0])[0]);photo_flags.append(0x14 if matches[0]==0 else 4)
 put(PHOTO_FLAGS,bytes(photo_flags))
 # Display projection only: stored roster slots retain their native role order.
 display_order=sorted(market.allowed,key=lambda uid:(-players[uid]['overall'],uid))
 assert len(display_order)==831
 put(OVR_SORTED,b''.join(struct.pack('>H',uid)for uid in display_order))
 put(PHOTOS,b''.join(struct.pack('>I',v)for v in photos));put(CURRENCY,struct.pack('>I',market.initial_currency));put(CATALOGUE_CRC,struct.pack('>I',market.catalogue_crc));ranks={u:i for i,u in enumerate(market.sort(market.allowed))};put(RANKS,b''.join(struct.pack('>H',ranks.get(i,65535))for i in range(832)));put(EMPTY,b'\0\2'+bytes(8));code=assemble('transfers',ENTRY);assert len(code)<=0x2000;put(ENTRY,code)
 menu=assemble('transfers_menu',0x254000);assert len(menu)<=0x1000;put(0x254000,menu)
 ui=assemble('transfers_ui',0x250000);assert len(ui)<=0x0C00;put(0x250000,ui)
 reset=assemble('transfers_reset',0x256000);assert len(reset)<=0x2000;put(0x256000,reset)
 patch(0x1F9A40,bytes.fromhex('7000223c00002000'),bytes.fromhex('4eb9002560004e71'))
 runtime=assemble('transfers_runtime',0x236000);assert len(runtime)<=0x2000;put(0x236000,runtime)
 def hook(at,old,entry,tail=False):
  old=bytes.fromhex(old);new=bytes.fromhex('4ef9'if tail else'4eb9')+struct.pack('>I',0x236000+entry)+bytes.fromhex('4e71')*((len(old)-6)//2);assert len(new)==len(old);patch(at,old,new)
 hook(0x17102,'3f38c6f43f38ca5848e70070',0,True)
 hook(0x9F40,'48e74080206a001e',16,True)
 hook(0x9F5C,'48e7008061de',20,True)
 hook(0x9F7E,'48e70080206a001e',24,True)
 hook(0x9F9A,'48e70080206a001e',28,True)
 hook(0xFAA3E,'d0d0d0d0504851c8fffa',32)
 hook(0x18BC8,'206a001ed0d0',36,True)
 hook(0xFAE26,'48e7ff7e4eb90022c018',60,True)
 hook(0xF894E,'2070000031f03004d43420703000',64)
 hook(0xF8906,'0c79001affffd43e',68)
 hook(0xF8A46,'24720000d4d23038d43460000006d4d2504a51c8fffa',72)
 hook(0x171CE,'4a78d05867000020',76,True)
 hook(0xF71FC,'2068001ed0e80006',80)
 hook(0xFAFE4,'2068001ed0e80006',80)
 hook(0xFD492,'2068001ed0e80006',80)
 hook(0x15B9A,'d0d0d0d0504851cbfffa5148',84)
 hook(0x96DA,'226a001ed2d1320051495049d2d151c9fffa',88)
 hook(0x9EE8,'226a001ed2d13400534260000006d2d1504951cafffa',92)
 hook(0x12E24,'226a001ed2d1e248d2d1504951c8fffa',96)
 hook(0x17986,'2269001ed2d160000006d2d1504951c9fffa',100)
 hook(0xFACA8,'2068001e321048c1d1c1321048c1d1c1508851c8fff65188',104)
 hook(0xEE82,'0c520002670000c4',108,True)
 hook(0xF9A04,'d4d2300160000006d4d2504a51c8fffa',112)
 hook(0xFA382,'60000006d4d2504a51c8fffa',116)
 hook(0xFA95E,'20503428000648c2d1c2',136)
 hook(0xFAB7C,'3f004eb900009f5cb057',140,True)
 return dict(status='Private native pricing/CRC/record-validation engine; menu/transactions/roster integration not complete',initial_budget=16042,price='native zero-hot-cold overall squared',currency=market.initial_currency,catalogue_crc=market.catalogue_crc,unique_players=831,aliases=market.aliases,addresses=dict(engine=ENTRY,initial=INITIAL,player_records=PLAYERS,prices=PRICES,positions=POSITIONS,overall=OVERALLS,photos=PHOTOS,currency=CURRENCY,catalogue_crc=CATALOGUE_CRC,ranks=RANKS,empty=EMPTY,display_overall_order=OVR_SORTED),native_code_bytes=len(code))
