"""
Loop Grid: a slanted desk with an 8 by 8 grid of lit pads, a row for each
element and a column for each loop, a big tempo knob, a covered lever that
throws the focus lock, and the bridge's stop button, activate button, light and
antenna. The bridge's board lives inside, on a printed tray.

Run from the cad/ folder:

    uv run loop-grid/model.py

It writes, for the site:
    site/public/files/loop-grid/stl/*.stl         cheeks, panel tiles and tray, laid flat
    site/public/files/loop-grid/loop-grid-stl.zip
    site/public/files/loop-grid/loop-grid.step    the whole desk, for editing
    site/public/files/loop-grid/loop-grid.glb     the 3D model shown on the page
    site/public/files/loop-grid/loop-grid-cad.py  this script, and console.py beside it
    site/src/content/instruments/loop-grid/drawings/loop-grid-render.svg

Coordinates as in set-list/model.py: X across from the left cheek's inside
face, Y front to back, Z up; u across and v up the slope on the panel.

The pads are four bought 4 by 4 boards with silicone keys, side by side under
one square window. All numbers are a first design, untested in print.
"""

from pathlib import Path
import sys

HERE = Path(__file__).resolve().parent
sys.path.insert(0, str(HERE.parent))
import console as c  # noqa: E402

# ---------------------------------------------------------------------------
# The design, in one place
# ---------------------------------------------------------------------------

DESK = c.Desk(w=320.0, d=190.0, front=50.0, back=100.0, tiles=[0.0, 160.0, 320.0])

GRID = (85.0, 100.0)  # the middle of the 8 x 8 pads
PAD_PITCH = 15.0  # the keys of a 4 x 4 board, 60 mm square
WINDOW = 8 * PAD_PITCH + 2.0
TEMPO = (215.0, 140.0)
LOCK = (215.0, 62.0)
STOP = (290.0, 135.0)
RELEASE = (278.0, 58.0)
LIGHT = (305.0, 58.0)
ANTENNA = (268.0, 178.0)
KNOB_HOLE, LOCK_HOLE = 7.5, 12.2  # an encoder's 7 mm shaft bushing; a toggle's 12 mm thread
STOP_D, RELEASE_D, LED_D, SMA_D = 22.4, 16.2, 8.0, 6.5

HOLES = [
    (*TEMPO, KNOB_HOLE),
    (*LOCK, LOCK_HOLE),
    (*STOP, STOP_D),
    (*RELEASE, RELEASE_D),
    (*LIGHT, LED_D),
    (*ANTENNA, SMA_D),
]
WINDOWS = [(*GRID, WINDOW, WINDOW)]

TRAY = (40.0, 200.0)
BOARDS = (110.0, 60.0)


def printed_parts():
    d = DESK
    tiles = [
        (f"panel-{i + 1}", d.tile(x0, x1, holes=HOLES, windows=WINDOWS), d.tile_flat())
        for i, (x0, x1) in enumerate(zip(d.tiles, d.tiles[1:]))
    ]
    return tiles + [
        ("cheek-left", d.cheek(False), c.Rot(0, 90, 0)),
        ("cheek-right", d.cheek(True), c.Rot(0, 90, 0)),
        ("tray", d.tray(*TRAY), c.Rot(0, 0, 0)),
    ]


def bought_parts():
    d = DESK
    parts = [(f"rail-{i + 1}", r, (0.78, 0.8, 0.83)) for i, r in enumerate(d.rails())]
    parts += [
        ("pads", d.place(c.pads(8, 8, PAD_PITCH), *GRID), (0.9, 0.9, 0.88)),
        ("tempo-knob", d.place(c.knob(), *TEMPO), (0.15, 0.15, 0.15)),
        ("lock-lever", d.place(c.lever(), *LOCK), (0.8, 0.15, 0.12)),
        ("stop-button", d.place(c.stop_button(), *STOP), (0.8, 0.15, 0.12)),
        ("release-button", d.place(c.push_button(), *RELEASE), (0.15, 0.15, 0.15)),
        ("status-light", d.place(c.light(), *LIGHT), (0.92, 0.92, 0.9)),
        ("antenna", d.place(c.antenna(), *ANTENNA), (0.12, 0.12, 0.12)),
        ("esp32-s3-board", c.Pos(BOARDS[0], BOARDS[1], 23) * c.boards(), (0.1, 0.25, 0.15)),
        ("feet", c.Compound(children=d.feet()), (0.1, 0.1, 0.1)),
    ]
    return parts


def main():
    d = DESK
    c.export(
        "loop-grid",
        __file__,
        printed_parts(),
        bought_parts(),
        [(None, (d.w + 240, -420, 440), (d.w / 2, d.d / 2, 45), "THE DESK: THE 8 x 8 PADS, THE TEMPO KNOB, THE LOCK LEVER AND THE STOP")],
        "Loop Grid: the desk",
    )


if __name__ == "__main__":
    main()
