import cadquery2 as cq
from cadquery2 import exporters

# Base for the notebook. Basically a kbd base that extends back
# as much as possible

# Thickness of the outer material
shell_t = 3

# Size of the kbd board
kbd_height = 98
kbd_width = 286
kbd_angle = 5

# Size of the whole object
width = kbd_width + 2 * shell_t
height = 164  # Max bed size
thickness = 20 + shell_t  # 20 inside

# Insert Positions
ti_radius = 2.35
ti_depth = 6.25

# Positions are determined by measuring the keyboard
# mounting holes
kbd_pillars = (
    cq.Sketch()
    .push(
        [
            (19, -16.5),
            (133, -16.5),
            (247.5, -16.5),
            (24, -86),
            (142.5, -91),
            (261.5, -86),
        ]
    )
    .circle(6, mode="a")
    # Holes for M3 threaded inserts
    .circle(ti_radius, mode="s")
)

# These are placed where convenient, and are used to join the top and bottom
# parts of the case.
# Measured from top-left corner OUTSIDE
mounting_pillar_positions = [
    (6, -6),
    (width - 6, -6),
    (width - 6, -40),
    (120, -6),
    (170, -6),
]

mounting_pillars = (
    cq.Sketch()
    .push(mounting_pillar_positions)
    .trapezoid(12, 12, 90, mode="a")
    .circle(1.8, mode="s")
)

screw_holes = cq.Sketch().push(mounting_pillar_positions).circle(3, mode="a")

battery_holder = (
    cq.Sketch()
    .polygon(
        [(-67, 5), (0, 5), (0, -12), (-67, -12), (-67, 5)],
        mode="a",
    )
    .trapezoid(83, 83, 90, mode="a")
    .trapezoid(80, 80, 90, mode="s")
    .polygon(
        [(-67, 3), (0, 3), (0, -10), (-67, -10), (-67, 3)],
        mode="s",
    )
    # Cutout for the
    .polygon(
        [(-67, 30), (0, 30), (0, 12), (-67, 12), (-67, 30)],
        mode="s",
    )
)


power_in = cq.Sketch().circle(5, mode="a")
usb_in = cq.Sketch().trapezoid(13, 5.5, 90, mode="a")
switch_in = cq.Sketch().trapezoid(13.5, 8.5, 90, mode="a")


# Motherboard mount


def model():
    return (
        cq.Workplane("XY")
        .workplane(offset=thickness / 2)
        .tag("mid_height")
        # Hollow box
        .box(width, height, thickness)
        .edges("|Z")
        .fillet(2)
        .faces(">Z")
        .shell(-shell_t)
        # Battery holder
        .workplaneFromTagged("mid_height")
        .center(-width / 2 + shell_t + 65, height / 2 - shell_t - 45)
        .placeSketch(battery_holder)
        .extrude(-height / 2)
        # Power cable inlet
        .faces("<X")
        .workplane(centerOption="CenterOfBoundBox")
        .center(-height / 2 + shell_t + 48.5, -3)
        .placeSketch(power_in)
        .cutBlind(-shell_t)
        # USB inlet
        .faces(">X")
        .workplane(centerOption="CenterOfBoundBox")
        .center(-height / 2 + shell_t + 50, -5)
        .placeSketch(usb_in)
        .cutBlind(-shell_t)
        # Hole for power switch
        .faces(">Y")
        .workplane(centerOption="CenterOfBoundBox")
        .center(0, 0)
        .placeSketch(switch_in)
        .cutBlind(-shell_t)
        # Slanted mounting pillars on the kbd top
        .faces(">Z")
        .workplane(centerOption="CenterOfBoundBox")
        # Top-left kbd corner inside the box
        .center(-width / 2 + shell_t, kbd_height - height / 2 + shell_t)
        .transformed(rotate=cq.Vector(kbd_angle, 0, 0))
        .tag("sloped")
        .placeSketch(kbd_pillars)
        .extrude(-1000)
        # Remove the excess extrusion
        .workplaneFromTagged("mid_height")
        .transformed(offset=cq.Vector(0, 0, -thickness / 2))
        .split(keepTop=True)
        # Slope for the beyboard
        .workplaneFromTagged("sloped")
        .split(keepBottom=True)
        # Pillars to join with top half
        .workplaneFromTagged("mid_height")
        .workplane(offset=-thickness / 2, centerOption="CenterOfBoundBox")
        .center(-width / 2, height / 2)
        .placeSketch(mounting_pillars)
        .extrude(thickness)
        # Holes to insert screws from the bottom
        .workplaneFromTagged("mid_height")
        .workplane(offset=-thickness / 2, centerOption="CenterOfBoundBox")
        .center(-width / 2, height / 2)
        .placeSketch(screw_holes)
        # 13 is 20-7 (screw thread length - threaded insert depth)
        .cutBlind(thickness - 13)
    )


if __name__ == "__main__":

    left_cutout = cq.Sketch().polygon(
        [(0, 0), (160, 0), (160, -100), (135, -100), (135, -200), (0, -200), (0, 0)],
        mode="a",
    )

    right_side = (
        model()
        .faces("<Z")
        .workplaneFromTagged("mid_height")
        .transformed(offset=cq.Vector(0, 0, -thickness / 2))
        .center(-width / 2, height / 2)
        .placeSketch(left_cutout)
        .cutBlind(100)
    )

    exporters.export(right_side, "right_side.stl")

    right_cutout = cq.Sketch().polygon(
        [
            (160, 0),
            (width, 0),
            (width, -height),
            (135, -height),
            (135, -100),
            (160, -100),
            (160, 0),
        ],
        mode="a",
    )

    left_side = (
        model()
        .faces("<Z")
        .workplaneFromTagged("mid_height")
        .transformed(offset=cq.Vector(0, 0, -thickness / 2))
        .center(-width / 2, height / 2)
        .placeSketch(right_cutout)
        .cutBlind(100)
    )
    exporters.export(left_side, "left_side.stl")

    exporters.export(model(), "model.stl")
