#!/usr/bin/env python3
"""Generate the CC0 rigid FBX equipment fixture with Blender.

Writes tests/fixtures/equipment/sword-fbx.fbx: a blade with the CC0 checker
texture embedded in the FBX and a plain-colour guard, and
sword-fbx-external.fbx: the same model referencing checker.png next to it
instead of embedding it. The files are exported
Z-up in centimetres so the importer has to perform the axis/unit
normalisation itself. Re-run when needed:

    blender --background --factory-startup --python scripts/make_fbx_equipment_fixture.py

Blender is only a fixture tool; the application never calls Blender.
"""

from pathlib import Path

import bpy

ROOT = Path(__file__).resolve().parents[1]
FIXTURES = ROOT / "tests" / "fixtures" / "equipment"
TARGET = FIXTURES / "sword-fbx.fbx"
EXTERNAL = FIXTURES / "sword-fbx-external.fbx"


def box(name, x0, x1, y0, y1, z0, z1, material):
    verts = [
        (x0, y0, z0), (x1, y0, z0), (x1, y1, z0), (x0, y1, z0),
        (x0, y0, z1), (x1, y0, z1), (x1, y1, z1), (x0, y1, z1),
    ]
    faces = [
        (0, 3, 2, 1), (4, 5, 6, 7), (0, 1, 5, 4),
        (1, 2, 6, 5), (2, 3, 7, 6), (3, 0, 4, 7),
    ]
    mesh = bpy.data.meshes.new(name)
    mesh.from_pydata(verts, [], faces)
    uv = mesh.uv_layers.new(name="UVMap")
    corners = [(0, 0), (1, 0), (1, 1), (0, 1)]
    for poly in mesh.polygons:
        for k, loop in enumerate(poly.loop_indices):
            uv.data[loop].uv = corners[k]
    mesh.materials.append(material)
    mesh.update()
    obj = bpy.data.objects.new(name, mesh)
    bpy.context.scene.collection.objects.link(obj)
    return obj


def main() -> None:
    bpy.ops.wm.read_factory_settings(use_empty=True)
    scene = bpy.context.scene
    scene.unit_settings.system = "METRIC"
    scene.unit_settings.scale_length = 1.0

    image = bpy.data.images.load(str(FIXTURES / "checker.png"))
    image.pack()
    blade_mat = bpy.data.materials.new("blade_checker")
    blade_mat.use_nodes = True
    bsdf = blade_mat.node_tree.nodes["Principled BSDF"]
    tex = blade_mat.node_tree.nodes.new("ShaderNodeTexImage")
    tex.image = image
    blade_mat.node_tree.links.new(tex.outputs["Color"], bsdf.inputs["Base Color"])

    guard_mat = bpy.data.materials.new("guard_brass")
    guard_mat.use_nodes = True
    guard_mat.node_tree.nodes["Principled BSDF"].inputs["Base Color"].default_value = (
        0.75, 0.55, 0.2, 1.0,
    )

    # Blender space: Z up. Blade 0.58 m long, guard at the bottom.
    box("blade", -0.03, 0.03, -0.01, 0.01, 0.03, 0.58, blade_mat)
    box("guard", -0.09, 0.09, -0.015, 0.015, 0.0, 0.03, guard_mat)

    common = dict(
        use_selection=False,
        object_types={"MESH"},
        axis_forward="Y",
        axis_up="Z",
        global_scale=1.0,
        apply_unit_scale=True,
        apply_scale_options="FBX_SCALE_NONE",
        bake_anim=False,
        add_leaf_bones=False,
    )
    bpy.ops.export_scene.fbx(
        filepath=str(TARGET), path_mode="COPY", embed_textures=True, **common
    )
    image.unpack(method="REMOVE")
    image.filepath = str(FIXTURES / "checker.png")
    bpy.ops.export_scene.fbx(
        filepath=str(EXTERNAL), path_mode="RELATIVE", embed_textures=False, **common
    )
    print("wrote", EXTERNAL)
    print("wrote", TARGET)


if __name__ == "__main__":
    main()
