import cadquery as cq
import cadkit as ck
import math

# Parameters
BAR_L = 120.0       # Length of the rack
BAR_W = 20.0        # Width of the rack
BAR_H = 20.0        # Height of the rack
NUM_TEETH = 19      # Number of teeth
PITCH = 6.28        # Tooth pitch (mm)
TOOTH_H = 4.5       # Tooth height
TOOTH_W_TOP = 2.5   # Top width of the trapezoidal tooth (approx for 20deg pressure angle)
TOOTH_W_BOT = 4.5   # Bottom width of the trapezoidal tooth
HOLE_D = 6.5        # Clearance hole diameter
HOLE_X_POS = 20.0    # Distance from end to hole center
HOLE_Z_POS = 5.0     # Height from bottom to hole center

# 1. Create the main block
# We start with a block. The teeth are carved out of the top.
# To make the teeth "stand" on the block, we define the base height as BAR_H - TOOTH_H
# but the prompt says the block is 120x20x20 and teeth are on the top face.
# Usually, a rack is a block with gaps cut out.
rack_base = cq.Workplane("XY").box(BAR_L, BAR_W, BAR_H, centered=(True, True, False))

# 2. Create the tooth cutter (trapezoidal profile)
# The profile is in XZ plane. 
# The tooth is a trapezoid. We want to cut the "gaps" between teeth.
# Gap width at top = PITCH - TOOTH_W_TOP
# Gap width at bottom = PITCH - TOOTH_W_BOT
gap_top = PITCH - TOOTH_W_TOP
gap_bot = PITCH - TOOTH_W_BOT

# Create a single gap cutter
gap_profile = (
    cq.Workplane("XZ")
    .center(0, BAR_H) # Start at the top surface
    .polyline([
        (-gap_top/2, 0), 
        (-gap_bot/2, -TOOTH_H), 
        (gap_bot/2, -TOOTH_H), 
        (gap_top/2, 0)
    ])
    .close()
    .extrude(BAR_W, both=True)
)

# 3. Array the gaps along the length
# We center the teeth on the bar.
start_x = -BAR_L/2 + PITCH/2
gaps = cq.Workplane("XY")

for i in range(NUM_TEETH):
    x_offset = start_x + i * PITCH
    gaps = gaps.union(gap_profile.translate((x_offset, 0, 0)))

# Subtract gaps from the block
rack = rack_base.cut(gaps)

# 4. Add side holes
# Holes are on the side (YZ plane), centered in width, at specific height
# We create a cylinder to cut the holes
hole_cutter = (
    cq.Workplane("XY")
    .workplane(offset=HOLE_Z_POS)
    .pushPoints([
        (-BAR_L/2 + HOLE_X_POS, 0), 
        (BAR_L/2 - HOLE_X_POS, 0)
    ])
    .circle(HOLE_D / 2)
    .extrude(BAR_W * 2, both=True)
)

rack = rack.cut(hole_cutter)

# Final touches: chamfers on the bottom edges for manufacturability
rack = rack.edges("<Z").chamfer(1.0)

# Assembly
assy = cq.Assembly()
assy.add(rack, name="gear_rack", color=cq.Color(0.7, 0.7, 0.7))

result = assy
