"""Prepare existing ImageGen masters in Aseprite; no generation or tests.

Requires local Aseprite and Pillow for read-only component analysis.
"""
from pathlib import Path
import argparse
import json
import shutil
import subprocess
import sys

ROOT=Path(__file__).resolve().parents[1]
parser=argparse.ArgumentParser()
parser.add_argument('--characters',nargs='+',default=['ganoes','commander','fiddler','surly'])
selection=parser.add_mutually_exclusive_group()
selection.add_argument('--gaits-only',action='store_true')
selection.add_argument('--poses-only',action='store_true')
selection.add_argument('--weight-only',action='store_true')
args=parser.parse_args()
aseprite=shutil.which('aseprite') or str(Path.home()/'.local/bin/aseprite')
cache=ROOT/'exports/motion-cache'
cache.mkdir(parents=True,exist_ok=True)
config={'ganoes':('ganoes_walk_v2',44,40),'commander':('commander_walk_v2',56,31),
        'fiddler':('fiddler_walk_v3',50,36),'surly':('surly_walk_v3',54,33)}
cast=json.loads((ROOT/'content/characters.json').read_text())

def analyse(source,rows,columns):
    boxes=cache/(source+'.lua')
    subprocess.run([sys.executable,str(ROOT/'tools/analyze_sheet.py'),str(ROOT/f'art/source/{source}.png'),
                    '--rows',str(rows),'--columns',str(columns),'--lua',str(boxes),
                    '--metadata',str(ROOT/f'art/source/{source}.frames.json')],check=True)
    return boxes

def export(script,params,label):
    command=[aseprite,'-b']
    for key,value in params.items():command+=['--script-param',f'{key}={value}']
    result=subprocess.run(command+['--script',str(ROOT/'tools'/script)],capture_output=True,text=True)
    (cache/(label+'.log')).write_text(result.stdout+result.stderr)
    if result.returncode:raise RuntimeError(f'Aseprite failed: {label}; see {cache}')
    print('Prepared',label,flush=True)

for name in ([] if args.poses_only else args.characters):
    template,height,cut=config[name]
    for mode in (['walk','run'] if name=='fiddler' else ['walk']):
        if args.weight_only and mode!='walk':continue
        motion=cast[name]
        source=motion['walk_source'] if mode=='walk' else motion['run_source']
        output=motion['walk_key_atlas'] if mode=='walk' else motion['run_atlas']
        stem=Path(output).stem
        if not args.weight_only:
            params={'source':ROOT/f'art/source/{source}.png','boxes':analyse(source,4,4),
                'template':ROOT/f'art/sprites/{template}.png','height':height,'head_cut':cut,
                'character':name,'mode':mode,'output':ROOT/output.removeprefix('res://'),
                'preview_prefix':ROOT/f'art/previews/{stem}'}
            if mode=='walk':params['idle']=ROOT/motion['idle_atlas'].removeprefix('res://')
            if mode=='walk' and motion.get('walk_preserve_anatomy'):
                # Keep the complete head, neck and torso from each source pose.
                # Equipment must never select a replacement head/back rectangle.
                params['source_native']='true'
            if name=='surly':
                params['source_native']='true'
                params['source_head_cuts']='37,35,35,30'
            export('export_walk_stable.lua',params,stem)
        if mode=='walk' and 'walk_phase_keys' in cast[name]:
            motion=cast[name]
            export('export_walk_weight.lua',{
                'source':ROOT/motion['walk_key_atlas'].removeprefix('res://'),
                'keys':','.join(map(str,motion['walk_phase_keys'])),
                'drops':','.join(map(str,motion['walk_phase_drops'])),
                'weights':','.join(map(str,motion['walk_frame_durations'])),
                'cycle':motion['walk_cycle_seconds'],
                'output':ROOT/motion['walk_atlas'].removeprefix('res://'),
                'preview':ROOT/motion['walk_preview']},name+'_walk_weight')

if not args.gaits_only and not args.weight_only:
    if 'ganoes' in args.characters:
        source='pose_ganoes_tiptoe_v2'
        export('export_tiptoe_lift.lua',{'source':ROOT/f'art/source/{source}.png',
               'boxes':analyse(source,1,3),'output':ROOT/'art/sprites/ganoes_tiptoe_v3.png',
               'preview_sheet':ROOT/'art/previews/ganoes_tiptoe_v3_sheet_3x.png',
               'preview':ROOT/'art/previews/ganoes_tiptoe_v3.gif'},source)
    for name,height in [('commander',58),('fiddler',52)]:
        if name in args.characters:
            source=f'pose_{name}_lean_v2'
            # Preserve the generated bent arms. Wide idle-template patches erased
            # shoulders/forearms as well as replacing the head in the old export.
            export('export_held_pose.lua',{'source':ROOT/f'art/source/{source}.png',
                   'height':height,'character':name,
                   'output':ROOT/f'art/sprites/{name}_lean_v3.png',
                   'preview':ROOT/f'art/previews/{name}_lean_v3_3x.png'},source)
