"""Reproduce the Hafner endpoint transfer using only split/move history."""
import argparse
import hashlib
import json
from pathlib import Path

from construction.history import verify_history
from construction.language import execute_steps
from construction.primitives import Motion

ROOT = Path(__file__).resolve().parents[2]
RECIPE = Path(__file__).with_name('hafner_nineteen_splits.geom')


def build():
    model = execute_steps(RECIPE.read_text(), filename=str(RECIPE.relative_to(ROOT)))
    membership = model.finish_membership()
    certificate = model.certificate()
    report = verify_history(json.loads(json.dumps(certificate)), expected_problem={'kind':'hafner_face_transfer'})
    moves = [event for event in certificate['history'] if event['op']=='move']
    nonidentity = sum(Motion(event['motion']['rotation'], event['motion']['translation']).rotation
                      != Motion().rotation for event in moves)
    if (report['split_operations'], report['move_operations'], report['physical_pieces'],
            nonidentity, report['checked_face_contacts']) != (19,20,21,20,20):
        raise ValueError('Unexpected pyramid-transfer history')
    report['proper_nonidentity_rotations'] = nonidentity
    report['construction'] = 'Hafner step 1: split the icosahedron and transfer its 20 pyramids'
    report['stationary_piece'] = 'icosidodecahedron'
    report['finish_assemblies'] = membership
    report['source_files_sha256'] = {
        str(path.relative_to(ROOT)):hashlib.sha256(path.read_bytes()).hexdigest()
        for path in [ROOT/'construction/library/geometry.geom',RECIPE,Path(__file__),
                     *(ROOT/f'construction/{name}.py' for name in
                       ('arrays','history','contact','pieces','goals','primitives','solids','vocabulary','relations','definitions','cycle_syntax','subroutines','language')),
                     *(ROOT/f'experiments/certification/{name}.py' for name in
                       ('field','geometry','partition','certificate'))]}
    return certificate,report


def main():
    parser=argparse.ArgumentParser(description=__doc__)
    parser.add_argument('--output-dir',type=Path)
    args=parser.parse_args()
    certificate,report=build()
    if args.output_dir:
        args.output_dir.mkdir(parents=True,exist_ok=True)
        (args.output_dir/'history.json').write_text(json.dumps(certificate,indent=2)+'\n')
        (args.output_dir/'verification.json').write_text(json.dumps(report,indent=2)+'\n')
    print(f"Exact transfer: {report['split_operations']} splits, {report['move_operations']} moves, "
          f"{report['physical_pieces']} physical pieces (including the stationary solid).")
    print(f"All split children connected; at most {report['max_internal_cells_per_piece']} internal convex cells per piece.")
    print('20 exact outward face contacts; 210 final physical-piece pair checks; zero missing material.')


if __name__=='__main__': main()
