# Render extension artifact pairs and explicitly labeled geometry-only inspection sections.
import argparse
import json
from pathlib import Path
import subprocess
import sys
import hearth_extensions
from hearth.persistence import load_scene, companion_path
from examples.preview import render, CUTAWAY


def views(seed, source, output, size=1100, sections=False, focus=None):
    scene = load_scene(source)
    if scene.seed != seed:
        raise ValueError('Explicit seed must match artifact')
    output.mkdir(parents=True, exist_ok=True)
    records = []
    offset = list(json.loads(companion_path(source).read_text())['offset'])
    render_source = source
    if focus:
        box = scene.view.contract(focus).envelope
        for index, axis in enumerate('xyz'):
            for keep_above, limit in ((False, box.hi[index]), (True, box.lo[index] - 1)):
                target = output / f'focus-{axis}-{int(keep_above)}.litematic'
                command = [sys.executable, str(CUTAWAY), '--input', str(render_source), '--output', str(target), '--axis', axis, '--max', str(limit - offset[index]), '--name', 'focus-preview']
                if keep_above:
                    command.append('--keep-above')
                subprocess.run(command, check=True)
                if keep_above:
                    offset[index] = limit + 1
                render_source = target
    for label, azimuth, elevation in (('front', 215, 36), ('rear', 35, 32), ('side', 120, 27)):
        target = output / (label + '.png')
        render(render_source, target, azimuth, elevation, size, 3.6)
        records.append({'source': str(source), 'seed': seed, 'label': label, 'azimuth': azimuth, 'elevation': elevation, 'image': str(target), 'focus': focus, 'geometry_preview_only': focus is not None})
    if sections:
        halls = [n for n in scene.nodes.values() if n.type == 'extension.pavilion']
        links = [n for n in scene.nodes.values() if n.type in ('extension.bridge', 'extension.gallery')]
        height = max(n.frame.origin[1] + n.contract.decisions['floor'] + 3 for n in halls) if halls else max(p[1] for n in links for p in scene.cells(n.path + '/deck')) + 1
        cuts = [('floor-cut', 'y', height, 215, 65)]
        if links:
            points = scene.cells(links[0].path + '/deck')
            cuts.append(('connection-section', 'x', (min(p[0] for p in points) + max(p[0] for p in points)) // 2, 110, 20))
        for label, axis, world, azimuth, elevation in cuts:
            target = output / (label + '.litematic')
            limit = world - offset['xyz'.index(axis)]
            subprocess.run([sys.executable, str(CUTAWAY), '--input', str(render_source), '--output', str(target), '--axis', axis, '--max', str(limit), '--name', label], check=True)
            image = output / (label + '.png')
            render(target, image, azimuth, elevation, size, 3.6)
            records.append({'source': str(source), 'seed': seed, 'label': label, 'axis': axis, 'world_cut': world, 'export_local_cut': limit, 'geometry_preview_only': True, 'image': str(image), 'focus': focus})
    (output / 'views.json').write_text(json.dumps(records, indent=2))


if __name__ == '__main__':
    p = argparse.ArgumentParser()
    p.add_argument('--seed', type=int, default=0)
    p.add_argument('--input', type=Path, required=True)
    p.add_argument('--output', type=Path, required=True)
    p.add_argument('--size', type=int, default=1100)
    p.add_argument('--sections', action='store_true')
    p.add_argument('--focus', help='Optional public component path for a geometry-only detail crop')
    a = p.parse_args()
    views(a.seed, a.input, a.output, a.size, a.sections, a.focus)
