# New post-fix operation compositions, predeclared separately from the regression corpus.
import argparse
import json
from pathlib import Path
from hearth import Scene
from hearth.environment import Terrain, gradient, wave, radial
from hearth.randomness import Scope
from hearth.components.building import adapted
from hearth.lodges import high_house, gabled_hall
from hearth.quality_assessment import DOMAIN, evaluate, summary
from hearth.persistence import semantic_digest


def run(seed, output, artifacts):
    output.mkdir(parents=True, exist_ok=True)
    artifacts.mkdir(parents=True, exist_ok=True)
    environments, inputs, rows = [], [], []
    for index in range(8):
        es = 3000 + seed * 100 + index
        rng = Scope(es).stream('new-expression')
        field = (gradient(rng.choice((-.04, 0, .04)), rng.choice((-.03, 0, .03)), 4) + wave(.35, .17, .05, rng.random() * 6))
        field = field.blend(gradient(-.02, .03, 4) + radial(13, 10, 25, .7), radial(5, 8, 32, .8)).transformed(dx=2, dz=-3, scale=1.1).clamp(2, 7)
        water = rng.choice((None, 5, 6))
        env = Scene(es, domain=DOMAIN)
        env.place('land', Terrain(DOMAIN, field, water))
        env.finalize()
        environments.append(env)
        inputs.append({'environment_seed': es, 'expression': field.expression(), 'water': water, 'digest': semantic_digest(env)})
    (output / 'frozen-inputs.json').write_text(json.dumps(inputs, indent=2))
    for index, env in enumerate(environments):
        for client, bs in ((high_house, 5), (gabled_hall, 7)):

            def recipe(e=env, c=client, b=bs):
                s = e.fork(seed=b)
                s.compose_choice(adapted('building', c(b), '/land'))
                return s.finalize()

            label = f'{index}-{client.__name__}-{bs}'
            artifact = artifacts / (label + '.litematic') if index == 0 else None
            rows.append(evaluate(label, {**inputs[index], 'client': client.__name__, 'structure_seed': bs}, recipe, artifact))
            if semantic_digest(env) != inputs[index]['digest']:
                raise AssertionError('Frozen input mutated')
            (output / 'results.json').write_text(json.dumps(rows, indent=2))
            print(label, rows[-1]['status'], flush=True)
    report = summary(rows)
    (output / 'summary.json').write_text(json.dumps(report, indent=2))
    (artifacts / 'manifest.json').write_text(json.dumps([r for r in rows if 'artifact' in r], indent=2))
    return report


if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('--seed', type=int, default=0)
    parser.add_argument('--output', type=Path, default=Path('reports/building-quality/holdout'))
    parser.add_argument('--artifacts', type=Path, default=Path('samples/building-quality/holdout'))
    args = parser.parse_args()
    print(json.dumps(run(args.seed, args.output, args.artifacts), indent=2))
