"""Render an original material comparison with fixed mesh camera and lights."""

import argparse
import json
import sys
from pathlib import Path

import bpy
from mathutils import Vector

p = argparse.ArgumentParser(description=__doc__)
p.add_argument("inputs", type=Path)
p.add_argument("output", type=Path)
a = p.parse_args(sys.argv[sys.argv.index("--") + 1 :])
a.output.mkdir()
bpy.ops.object.select_all(action="SELECT")
bpy.ops.object.delete(use_global=False)
s = bpy.context.scene
s.render.engine = "CYCLES"
s.cycles.samples = 48
s.cycles.use_adaptive_sampling = False
s.cycles.seed = 11
s.render.resolution_x = 1100
s.render.resolution_y = 800
s.render.resolution_percentage = 100
s.render.pixel_aspect_x = s.render.pixel_aspect_y = 1
s.world.color = (0.06, 0.06, 0.06)


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


m = material("Original teal finish", (0.025, 0.24, 0.21), 0.21)
n = m.node_tree.nodes.get("Principled BSDF")
n.inputs["Metallic"].default_value = 0
n.inputs["IOR"].default_value = 1.5
tex = m.node_tree.nodes.new("ShaderNodeTexImage")
tex.image = bpy.data.images.load(str(a.inputs / "specular-default-mask.png"))
tex.image.colorspace_settings.name = "Non-Color"
tex.image.pack()
tex.interpolation = "Linear"
bpy.ops.mesh.primitive_plane_add(size=2, location=(0, 0, 0.15))
panel = bpy.context.object
panel.name = "Fixed finish panel"
panel.scale = (1.6, 1, 1)
panel.data.materials.append(m)
bpy.ops.mesh.primitive_cube_add(size=1, location=(0, 0, 0.02))
base = bpy.context.object
base.name = "Original beveled support"
base.scale = (3.4, 2.2, 0.22)
bpy.ops.object.transform_apply(location=False, rotation=False, scale=True)
base.data.materials.append(material("Dark navy support", (0.015, 0.025, 0.045), 0.28))
bevel = base.modifiers.new("Support bevel", "BEVEL")
bevel.width = 0.1
bevel.segments = 4
base.modifiers.new("Support normals", "WEIGHTED_NORMAL")
bpy.ops.object.camera_add(location=(2.7, -4.4, 5))
cam = bpy.context.object
cam.name = "Fixed finish camera"
cam.rotation_euler = (Vector((0, 0, 0.1)) - cam.location).to_track_quat("-Z", "Y").to_euler()
cam.data.type = "ORTHO"
cam.data.ortho_scale = 4.7
s.camera = cam
for loc, power, size in [((-2.5, 3.8, 5), 1200, 4), ((0, -3, 3), 180, 3)]:
    bpy.ops.object.light_add(type="AREA", location=loc)
    light = bpy.context.object
    light.data.energy = power
    light.data.size = size
    light.rotation_euler = (
        (Vector((0, 0, 0.1)) - light.location).to_track_quat("-Z", "Y").to_euler()
    )


def setup(mode):
    for key in ["Specular IOR Level", "Roughness"]:
        for link in list(n.inputs[key].links):
            m.node_tree.links.remove(link)
    n.inputs["Specular IOR Level"].default_value = 0.5
    n.inputs["Roughness"].default_value = 0.21
    if mode == "specular":
        m.node_tree.links.new(tex.outputs["Color"], n.inputs["Specular IOR Level"])
    if mode == "roughness":
        m.node_tree.links.new(tex.outputs["Color"], n.inputs["Roughness"])


records = []
for mode in ["uniform", "specular", "roughness"]:
    setup(mode)
    s.render.filepath = str(a.output / f"specular-native-{mode}.png")
    bpy.ops.render.render(write_still=True)
    records.append(
        {
            "mode": mode,
            "imageColorSpace": tex.image.colorspace_settings.name,
            "imageSocket": "Specular IOR Level"
            if mode == "specular"
            else "Roughness"
            if mode == "roughness"
            else None,
            "unlinkedSpecularIORLevel": 0.5,
            "unlinkedRoughness": 0.21,
            "IOR": 1.5,
            "metallic": 0,
            "panelVertices": len(panel.data.vertices),
            "panelModifiers": len(panel.modifiers),
            "cameraMatrix": [list(row) for row in cam.matrix_world],
        }
    )
setup("specular")
bpy.ops.wm.save_as_mainfile(filepath=str(a.output / "specular-material-study.blend"))
(a.output / "specular-native-record.json").write_text(
    json.dumps(
        {
            "Blender": bpy.app.version_string,
            "scope": "Original fixed native shader-input comparison not measured reflectance or an AI PBR material",
            "size": [1100, 800],
            "records": records,
        },
        indent=2,
    )
    + "\n"
)
