import cadquery as cq
import math

# Size of the kbd board
kbd_height = 95.5
kbd_width = 305
back_thickness = 19
front_thickness = 12

# Pythagoras
actual_height = (kbd_height**2 - (back_thickness - front_thickness) ** 2) ** 0.5
kbd_angle = math.acos(actual_height / kbd_height) * 180 / math.pi

kbd_pillar_positions = [
    (19, 16),
    (142.5, 25.5),
    (kbd_width - 20, 16),
    (23.5, 79.5),
    (145.5, 82.5),
    (kbd_width - 19, 79.5),
]

elements = [
    # Shorter pillars
    {
        "x": 0,
        "y": 0,
        "z": 5.5,
        "shape": cq.Sketch().push(kbd_pillar_positions).circle(5, mode="a"),
    },
    # Taller pillars with holes for self-tapping screws
    {
        "x": 0,
        "y": 0,
        "z": 2.5,
        "shape": (
            cq.Sketch()
            .push(kbd_pillar_positions)
            .circle(2.4, mode="a")
            .circle(1.1, mode="s")
        ),
    },
]


def add(
    *,
    model,
    width,
    height,
    thickness,
    offset_x,
    offset_y,
    bottom_face,
    back_face,
    shell_t
):
    # This one is special, it creates angled things and cuts off the
    # case, so ... it's going to do weird stuff

    if bottom_face:
        model = (
            model.faces(bottom_face)
            .workplane(centerOption="CenterOfBoundBox", offset=-front_thickness)
            .center(
                -width / 2,
                height / 2,
            )
            .transformed(rotate=cq.Vector(kbd_angle, 0, 0))
            .tag("kbd_sloped")
        )
        for element in elements:
            model = (
                model.workplaneFromTagged("kbd_sloped")
                .center(offset_x + element["x"], -offset_y - element["y"])
                .workplane(offset=element["z"])
                .placeSketch(element["shape"])
                .extrude(100)
            )

        model = (
            model.workplaneFromTagged("mid_height")
            .transformed(offset=cq.Vector(0, 0, -thickness / 2))
            .split(keepTop=True)
            .faces(">X")
            .workplane(centerOption="CenterOfBoundBox")
            .center(-height / 2, -thickness / 2)
            .placeSketch(
                cq.Sketch().polygon(
                    [
                        [0, front_thickness],
                        [shell_t, front_thickness],
                        [actual_height + shell_t, back_thickness],
                        [actual_height + shell_t, 1000],
                        [0, 1000],
                        [0, front_thickness],
                    ]
                )
            )
            .cutBlind(-1000)
        )

    return model
