#!/usr/bin/env python3
"""Render V2 candidates in clay and strip-reflection studios."""

from __future__ import annotations

import math
import sys
from pathlib import Path

import bpy
from mathutils import Vector


def clear() -> None:
    bpy.ops.object.select_all(action="SELECT")
    bpy.ops.object.delete(use_global=False)
    for material in list(bpy.data.materials):
        if material.users == 0:
            bpy.data.materials.remove(material)


def import_mesh(path: Path) -> bpy.types.Object:
    bpy.ops.import_scene.gltf(filepath=str(path))
    obj = max((item for item in bpy.context.scene.objects if item.type == "MESH"), key=lambda item: len(item.data.vertices))
    for polygon in obj.data.polygons:
        polygon.use_smooth = True
    return obj


def point_at(obj: bpy.types.Object, target: Vector) -> None:
    obj.rotation_euler = (target - obj.location).to_track_quat("-Z", "Y").to_euler()


def add_area(name: str, location: Vector, energy: float, size: float, size_y: float, target: Vector) -> None:
    light_data = bpy.data.lights.new(name, "AREA")
    light_data.energy = energy
    light_data.shape = "RECTANGLE"
    light_data.size = size
    light_data.size_y = size_y
    light = bpy.data.objects.new(name, light_data)
    bpy.context.collection.objects.link(light)
    light.location = location
    point_at(light, target)


def setup_scene(output: Path) -> None:
    scene = bpy.context.scene
    scene.render.engine = "BLENDER_EEVEE"
    scene.render.resolution_x = 760
    scene.render.resolution_y = 760
    scene.render.resolution_percentage = 100
    scene.render.image_settings.file_format = "PNG"
    scene.render.image_settings.color_mode = "RGBA"
    scene.render.filepath = str(output)
    scene.world.use_nodes = True
    background = scene.world.node_tree.nodes.get("Background")
    background.inputs["Color"].default_value = (0.035, 0.038, 0.045, 1.0)
    background.inputs["Strength"].default_value = 0.3
    scene.view_settings.look = "AgX - Medium High Contrast"
    scene.view_settings.exposure = 0.5

    camera_data = bpy.data.cameras.new("Camera")
    camera_data.lens = 62
    camera = bpy.data.objects.new("Camera", camera_data)
    bpy.context.collection.objects.link(camera)
    camera.location = (0.0, -4.55, 3.55)
    point_at(camera, Vector((0.0, 0.0, -0.015)))
    scene.camera = camera

    # Thin strip lights deliberately reveal curvature continuity.
    add_area("Left strip", Vector((-2.8, -2.6, 3.2)), 1250, 0.38, 4.4, Vector())
    add_area("Right strip", Vector((3.0, -1.8, 2.0)), 1050, 0.32, 4.0, Vector())
    add_area("Rear strip", Vector((0.5, 3.0, 3.4)), 1400, 0.30, 3.6, Vector())
    add_area("Top card", Vector((0.0, -0.2, 4.5)), 700, 3.0, 2.2, Vector())

    bpy.ops.mesh.primitive_plane_add(size=8.0, location=(0.0, 0.0, -0.27))
    floor = bpy.context.object
    floor_mat = bpy.data.materials.new("Floor")
    floor_mat.use_nodes = True
    floor_bsdf = floor_mat.node_tree.nodes.get("Principled BSDF")
    floor_bsdf.inputs["Base Color"].default_value = (0.06, 0.065, 0.075, 1.0)
    floor_bsdf.inputs["Roughness"].default_value = 0.32
    floor.data.materials.append(floor_mat)


def main() -> None:
    args = sys.argv[sys.argv.index("--") + 1 :]
    output = Path(args[0]).resolve()
    sources = [Path(item).resolve() for item in args[1:]]
    output.mkdir(parents=True, exist_ok=True)
    for source in sources:
        clear()
        ring = import_mesh(source)
        setup_scene(output / f"{source.stem}-hero.png")
        scene = bpy.context.scene
        scene.render.filepath = str(output / f"{source.stem}-hero.png")
        bpy.ops.render.render(write_still=True)
        camera = scene.camera
        camera.location = (0.0, -5.25, 0.35)
        point_at(camera, Vector((0.0, 0.0, -0.02)))
        scene.render.filepath = str(output / f"{source.stem}-front.png")
        bpy.ops.render.render(write_still=True)
        camera.location = (0.0, -3.95, -3.45)
        point_at(camera, Vector((0.0, 0.0, -0.02)))
        scene.render.filepath = str(output / f"{source.stem}-under.png")
        bpy.ops.render.render(write_still=True)


if __name__ == "__main__":
    main()
