"""Check renders of the Coral Eye assembly (system python: numpy + Pillow)."""
import os
import sys
import numpy as np

HERE = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, HERE)
from render import Mesh, Camera, render, load_stl  # noqa: E402

M = os.path.normpath(os.path.join(HERE, "..", "render", "meshes"))
R = os.path.normpath(os.path.join(HERE, "..", "render"))
BOARD = os.path.normpath(os.path.join(HERE, "..", "..", "referencia-oficial", "Synaptics_CoralBoard_SL.stl"))

FACE_COL = (232, 233, 228)      # warm white
BODY_COL = (58, 62, 70)         # graphite
CORAL = (255, 111, 97)


def parts(explode=0.0, with_face=True, with_body=True, board=True, face_col=FACE_COL, body_col=BODY_COL, ring_col=CORAL,
          shutter="open"):
    out = []
    if with_body:
        out.append(Mesh(load_stl(os.path.join(M, "body.stl")), body_col, 0.18, 30, "body"))
        out.append(Mesh(load_stl(os.path.join(M, "screws_back.stl")), (140, 142, 146), 0.6, 60, "screws_back"))
        out.append(Mesh(load_stl(os.path.join(M, "plunger.stl")), body_col, 0.18, 30, "plunger"))
    if board:
        b = load_stl(BOARD)
        out.append(Mesh(b + [0, 0, explode * 0.0], (236, 238, 236), 0.10, 20, "board"))
    out.append(Mesh(load_stl(os.path.join(M, "cable.stl")) + [0, 0, explode * 0.35], (214, 128, 40), 0.3, 30, "cable"))
    out.append(Mesh(load_stl(os.path.join(M, "cam_pcb.stl")) + [0, 0, explode * 0.6], (30, 110, 60), 0.2, 30, "campcb"))
    out.append(Mesh(load_stl(os.path.join(M, "cam_conn.stl")) + [0, 0, explode * 0.6], (60, 60, 60), 0.2, 30, "camconn"))
    out.append(Mesh(load_stl(os.path.join(M, "cam_lens.stl")) + [0, 0, explode * 0.6], (20, 20, 22), 0.6, 60, "lens"))
    if with_face:
        out.append(Mesh(load_stl(os.path.join(M, "face.stl")) + [0, 0, explode], face_col, 0.22, 35, "face"))
        if shutter:                     # twist shutter: "open", "half" or "closed"
            for k, col, spec, gloss, ex in (("twist", body_col, 0.25, 40, 1.2), ("blade_up", ring_col, 0.3, 40, 1.3),
                                            ("blade_down", ring_col, 0.3, 40, 1.3), ("bezel", ring_col, 0.35, 50, 1.45)):
                tris = load_stl(os.path.join(M, f"sh_{k}_{shutter}.stl")) + [0, 0, explode * ex]
                out.append(Mesh(tris, col, spec, gloss, k))
            out.append(Mesh(load_stl(os.path.join(M, "sh_screws.stl")) + [0, 0, explode * 1.45], (140, 142, 146),
                            0.6, 60, "bezel_screws"))
        else:                           # Lite option: plain glued ring
            out.append(Mesh(load_stl(os.path.join(M, "ring.stl")) + [0, 0, explode * 1.35], ring_col, 0.35, 50, "ring"))
    return out


AXIS_Y, AXIS_Z = -17.1, -16.7          # GoPro pivot (accessories.py)
BASE_Y = AXIS_Y - 8.5 - 15.0 - 6.0      # desk under the stand


def stand_parts(mount_col=(58, 62, 70)):
    out = [Mesh(load_stl(os.path.join(M, "CoralEye_Mount_GoPro.stl")), mount_col, 0.18, 30, "adapter"),
           Mesh(load_stl(os.path.join(M, "CoralEye_Stand.stl")), mount_col, 0.18, 30, "stand")]
    knob = load_stl(os.path.join(M, "..", "..", "out", "CoralEye_Stand_Knob.stl"))
    knob = knob - [0, 0, 0]
    R = np.array([[0, 0, -1], [0, 1, 0], [1, 0, 0]], float)
    knob = knob @ R.T + [32.7 - 6.3 - 1.5, AXIS_Y, AXIS_Z]
    out.append(Mesh(knob, CORAL, 0.3, 40, "knob"))
    return out


def view(name, eye, target=(32.7, 26.5, 3.0), fov=28, **kw):
    cam = Camera(eye, target, fov=fov, width=kw.pop("w", 1200), height=kw.pop("h", 900))
    meshes = kw.pop("meshes")
    im = render(meshes, cam, **kw)
    path = os.path.join(R, name)
    im.save(path)
    print("saved", path)


if __name__ == "__main__":
    which = sys.argv[1:] or ["front", "back", "explode", "open"]
    if "front" in which:
        view("check_front.png", eye=(-90, 70, 190), meshes=parts(), ss=2)
    if "back" in which:
        view("check_back.png", eye=(150, 40, -170), meshes=parts(), ss=2)
    if "explode" in which:
        view("check_explode.png", eye=(-160, 90, 160), target=(32.7, 26.5, 20), fov=34,
             meshes=parts(explode=45.0), ss=2)
    if "open" in which:
        view("check_open.png", eye=(-60, 60, 170), meshes=parts(with_face=False), ss=2)
    if "bottom" in which:
        view("check_bottom.png", eye=(20, -150, 90), meshes=parts(), ss=2)
    if "stand" in which:
        view("check_stand.png", eye=(-120, 60, 210), target=(32.7, 6.0, 0.0), fov=32,
             meshes=parts() + stand_parts(), ss=2, ground_y=BASE_Y)
    if "stand_back" in which:
        view("check_stand_back.png", eye=(170, 50, -170), target=(32.7, 6.0, -8.0), fov=32,
             meshes=parts() + stand_parts(), ss=2, ground_y=BASE_Y)
