"""Close-ups of the twist shutter (system python: numpy + Pillow).

    python3 -E render_shutter.py            -> render/gallery/10_shutter_states.png (open / half / closed)
    python3 -E render_shutter.py anim       -> render/gallery/11_shutter.gif from render/meshes/anim/
"""
import glob
import os
import sys

import numpy as np
from PIL import Image, ImageDraw, ImageFont

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

G = os.path.normpath(os.path.join(HERE, "..", "render", "gallery"))
LENS = (45.4, 20.3, 13.2)
EYE = (LENS[0] - 38, LENS[1] + 30, LENS[2] + 112)


def close_up(meshes, w=900, h=900, ss=2):
    cam = Camera(EYE, LENS, fov=21, width=w, height=h)
    return render(meshes, cam, ss=ss)


def label(im, text):
    d = ImageDraw.Draw(im)
    try:
        f = ImageFont.truetype("/System/Library/Fonts/Helvetica.ttc", 44)
    except OSError:
        f = ImageFont.load_default()
    tw = d.textlength(text, font=f)
    d.text(((im.width - tw) / 2, im.height - 80), text, fill=(60, 64, 72), font=f)
    return im


def states():
    ims = []
    for st, txt in (("open", "Open"), ("half", "Turning"), ("closed", "Closed")):
        body = [m for m in parts(shutter=st, board=False) if m.name in ("body", "face", "twist", "blade_up",
                                                                         "blade_down", "bezel", "lens", "campcb",
                                                                         "bezel_screws")]
        ims.append(label(close_up(body), txt))
    out = Image.new("RGB", (sum(i.width for i in ims), ims[0].height), (255, 255, 255))
    x = 0
    for i in ims:
        out.paste(i, (x, 0))
        x += i.width
    p = os.path.join(G, "10_shutter_states.png")
    out.save(p)
    print("saved", p)


def anim():
    frames_dir = os.path.join(M, "anim")
    base = [m for m in parts(shutter=None, board=False) if m.name in ("body", "face", "lens", "campcb")]
    base.append(Mesh(load_stl(os.path.join(M, "sh_screws.stl")), (140, 142, 146), 0.6, 60, "bezel_screws"))
    files = sorted(glob.glob(os.path.join(frames_dir, "f*_bezel.stl")))
    frames = []
    for f in files:
        tag = os.path.basename(f).split("_")[0]
        ms = list(base)
        for k, col, spec, gloss in (("twist", BODY_COL, 0.25, 40), ("blade_up", CORAL, 0.3, 40),
                                    ("blade_down", CORAL, 0.3, 40), ("bezel", CORAL, 0.35, 50)):
            ms.append(Mesh(load_stl(os.path.join(frames_dir, f"{tag}_{k}.stl")), col, spec, gloss, k))
        frames.append(close_up(ms, w=600, h=600, ss=2).convert("P", palette=Image.ADAPTIVE, colors=128))
        print("frame", tag)
    seq = frames + frames[::-1]
    durations = [600 if i in (0, len(frames) - 1, len(frames), len(seq) - 1) else 70 for i in range(len(seq))]
    p = os.path.join(G, "11_shutter.gif")
    seq[0].save(p, save_all=True, append_images=seq[1:], duration=durations, loop=0, optimize=True)
    print("saved", p)


if __name__ == "__main__":
    if "anim" in sys.argv[1:]:
        anim()
    else:
        states()
