"""Build an original proxy recording and material-only first-frame reference in Blender."""

import json
import sys
from pathlib import Path

import bpy
from bpy_extras.object_utils import world_to_camera_view
from mathutils import Vector

out = Path(sys.argv[sys.argv.index("--") + 1]).resolve()
out.mkdir()
(out / "frames").mkdir()
bpy.ops.object.select_all(action="SELECT")
bpy.ops.object.delete(use_global=False)
scene = bpy.context.scene
scene.render.engine = "BLENDER_EEVEE"
scene.render.resolution_x = 1280
scene.render.resolution_y = 704
scene.render.resolution_percentage = 100
scene.render.fps = 24
scene.render.image_settings.file_format = "PNG"
scene.frame_start = 1
scene.frame_end = 49
scene.world.color = (0.12, 0.12, 0.12)
scene.view_settings.view_transform = "Standard"
scene.view_settings.look = "Medium High Contrast"


def material(name, color):
    m = bpy.data.materials.new(name)
    m.use_nodes = True
    m.use_fake_user = True
    node = m.node_tree.nodes.get("Principled BSDF")
    node.inputs["Base Color"].default_value = (*color, 1)
    node.inputs["Roughness"].default_value = 0.7
    return m


proxy = material("Proxy neutral", (0.52, 0.54, 0.56))
colors = {
    "Parcel": material("Cover blue parcel", (0.04, 0.32, 0.72)),
    "Pillar": material("Cover clay pillar", (0.64, 0.24, 0.12)),
    "Floor": material("Cover pale teal floor", (0.35, 0.55, 0.54)),
    "Wall": material("Cover warm wall", (0.72, 0.65, 0.5)),
}


def cube(name, location, dimensions):
    bpy.ops.mesh.primitive_cube_add(size=1, location=location)
    obj = bpy.context.object
    obj.name = name
    obj.dimensions = dimensions
    bpy.ops.object.transform_apply(location=False, rotation=False, scale=True)
    obj.data.materials.append(proxy)
    return obj


floor = cube("Floor", (0, 0, -0.1), (8, 6, 0.2))
wall = cube("Wall", (0, 2.1, 1.4), (8, 0.2, 2.8))
pillar = cube("Pillar", (0, 0, 1.1), (0.7, 0.7, 2.2))
parcel = cube("Parcel", (-2.2, 0.65, 0.4), (0.8, 0.6, 0.8))
for frame, x in [(1, -2.2), (49, 2.2)]:
    parcel.location.x = x
    parcel.keyframe_insert(data_path="location", frame=frame)
# Store every pose explicitly so the original motion does not depend on curve defaults.
for frame in range(1, 50):
    parcel.location.x = -2.2 + 4.4 * (frame - 1) / 48
    parcel.keyframe_insert(data_path="location", frame=frame)

bpy.ops.object.camera_add(location=(0, -8, 4.5))
camera = bpy.context.object
camera.name = "Fixed proxy camera"
camera.rotation_euler = (Vector((0, 0, 0.8)) - camera.location).to_track_quat("-Z", "Y").to_euler()
camera.data.type = "ORTHO"
camera.data.ortho_scale = 7.4
scene.camera = camera
bpy.ops.object.light_add(type="AREA", location=(-3, -4, 7))
light = bpy.context.object
light.data.energy = 1100
light.data.shape = "DISK"
light.data.size = 5
light.rotation_euler = (Vector((0, 0, 0)) - light.location).to_track_quat("-Z", "Y").to_euler()
objects = [floor, wall, pillar, parcel]


def bounds(obj):
    points = [
        world_to_camera_view(scene, camera, obj.matrix_world @ Vector(v)) for v in obj.bound_box
    ]
    return [[float(p.x * 1280), float((1 - p.y) * 704)] for p in points]


scene.frame_set(1)
bpy.context.view_layer.update()
opening = {obj.name: bounds(obj) for obj in objects}
for obj in objects:
    obj.data.materials[0] = colors[obj.name]
scene.render.filepath = str(out / "cover.png")
bpy.ops.render.render(write_still=True)
assert opening == {obj.name: bounds(obj) for obj in objects}
for obj in objects:
    obj.data.materials[0] = proxy
records = []
for frame in range(1, 50):
    scene.frame_set(frame)
    bpy.context.view_layer.update()
    records.append(
        {
            "sourceFrame": frame - 1,
            "seconds": (frame - 1) / 24,
            "parcelPosition": list(parcel.location),
            "projectedCornersPixels": bounds(parcel),
        }
    )
    scene.render.filepath = str(out / "frames" / f"frame-{frame - 1:03d}.png")
    bpy.ops.render.render(write_still=True)
scene.frame_set(1)
bpy.ops.wm.save_as_mainfile(filepath=str(out / "eden-proxy-study.blend"))
measurements = {
    "blender": bpy.app.version_string,
    "engine": scene.render.engine,
    "width": 1280,
    "height": 704,
    "fps": 24,
    "frameCount": 49,
    "durationSeconds": 49 / 24,
    "cameraType": camera.data.type,
    "cameraLocation": list(camera.location),
    "cameraRotationRadians": list(camera.rotation_euler),
    "orthographicScale": camera.data.ortho_scale,
    "openingProjectedCornersPixels": opening,
    "coverProjectionMatchesProxyOpening": True,
    "frames": records,
    "note": "Original native Blender geometry and material-only cover with no EdenLive model execution",
}
(out / "eden-proxy-measurements.json").write_text(json.dumps(measurements, indent=2) + "\n")
print("EDEN_PROXY_STUDY_COMPLETE", out)
