# Kitchen: an L of base units along two walls, every drawer and door its own object (pick one and
# pull it out), an oak worktop with the sink cut into it, a cooktop and a hood, wall units, an
# island with stools, pendant lamps, a window in the wall.
from math import *
units("cm")

front_c, oak, wall_c, floor_c, steel = "#7d9c88", "#c49a6c", "#f2efe9", "#cfc8bd", "#c9ccd2"
dark, chrome = "#2f3033", "#dfe2e6"
H, TOP, DEPTH = 86, 4, 60           # the units' height, the worktop's thickness, their depth
GAP = 0.4                           # between fronts

# ---------- the room: a floor and two walls, a window in the back wall ----------
floor_ = box(620, 470, 4, at=(-12, -20, -4), name="floor", color=floor_c)
back_wall = box(632, 12, 270, at=(-12, 450, 0), name="back wall", color=wall_c)
back_wall = back_wall - box(150, 12, 105, at=(165, 450, 112))
back_wall.paint(wall_c)
left_wall = box(12, 470, 270, at=(-12, -20, 0), name="left wall", color=wall_c)
win = [box(150, 2, 105, at=(165, 455, 112), name="glass", color="glass")]
for x in (165, 237, 309):
    win.append(box(6, 8, 105, at=(x, 452, 112), name="window frame", color="#f4f2ec"))
for z in (112, 211):
    win.append(box(150, 8, 6, at=(165, 452, z), name="window frame", color="#f4f2ec"))
sill = box(162, 18, 3, at=(159, 438, 109), name="sill", color=oak)

# ---------- base units: carcasses, plinths, then the fronts ----------
units_ = []
units_.append(box(420, DEPTH - 2, H - 10, at=(0, 392, 10), name="carcass", color="#e9e6e0"))
units_.append(box(DEPTH - 2, 240, H - 10, at=(0, 150, 10), name="carcass", color="#e9e6e0"))
units_.append(box(420, DEPTH - 8, 10, at=(0, 398, 0), name="plinth", color=dark))
units_.append(box(DEPTH - 8, 240, 10, at=(0, 150, 0), name="plinth", color=dark))

fronts = []
def handle_bar(x, y, z, along):
    if along == "x":
        h = box(16, 2.5, 1.2, at=(x - 8, y - 2.5, z), name="handle", color=steel)
    else:
        h = box(2.5, 16, 1.2, at=(x, y - 8, z), name="handle", color=steel)
    return h
def front(a0, a1, z0, z1, side, name, kind):
    # side "back": along x, facing -y at y = 392; "left": along y, facing +x at x = 58
    w, h = a1 - a0 - GAP, z1 - z0 - GAP
    if side == "back":
        p = box(w, 2, h, at=(a0 + GAP / 2, 390, z0 + GAP / 2), name="front", color=front_c)
        hb = handle_bar((a0 + a1) / 2, 390, z1 - 7, "x")
    else:
        p = box(2, w, h, at=(58, a0 + GAP / 2, z0 + GAP / 2), name="front", color=front_c)
        hb = handle_bar(60, (a0 + a1) / 2, z1 - 7, "y")
    fronts.append(group([p, hb], name=name))

n = {"drawer": 0, "door": 0}
def nm(kind):
    n[kind] += 1
    return f"{kind} {n[kind]}"
# along the back wall: a drawer stack, the sink's two doors, doors, drawers
for a0, a1, kind in [(0, 60, "door"), (60, 120, "drawers"), (165, 240, "door"), (240, 315, "door"), (315, 370, "drawers"), (370, 420, "door")]:
    if kind == "door":
        front(a0, a1, 10, H, "back", nm("door"), kind)
    else:
        for z0, z1 in [(10, 36), (36, 61), (61, H)]:
            front(a0, a1, z0, z1, "back", nm("drawer"), kind)
front(120, 165, 10, H, "back", nm("door"), "door")
# along the left wall: drawers under the cooktop, doors
for a0, a1, kind in [(150, 210, "door"), (210, 300, "drawers"), (300, 390, "door")]:
    if kind == "door":
        front(a0, a1, 10, H, "left", nm("door"), kind)
    else:
        for z0, z1 in [(10, 36), (36, 61), (61, H)]:
            front(a0, a1, z0, z1, "left", nm("drawer"), kind)

# ---------- the worktop, with the sink cut into it ----------
worktop = box(424, DEPTH + 3, TOP, at=(0, 387, H), name="worktop", color=oak) + box(DEPTH + 3, 240, TOP, at=(0, 150, H), name="worktop", color=oak)
worktop = worktop - box(76, 42, TOP, at=(202, 402, H))
worktop.paint(oak)
worktop.fillet(0.6, edges="top")
basin = box(76, 42, 20, at=(202, 402, H + TOP - 20), name="sink", color=steel)
basin.fillet(4, edges="vertical")
basin.shell(1, open="top")
drain = cylinder(2.5, 0.5, at=(240, 423, H + TOP - 19.5), name="drain", color=dark, sides=16)
tap_base = cylinder(2.6, 6, at=(240, 440, H + TOP), name="tap", color=chrome, sides=24)
spout = pipe([(240, 440, H + TOP + 5), (240, 440, H + TOP + 30), (240, 434, H + TOP + 37), (240, 424, H + TOP + 34), (240, 420, H + TOP + 24)], 1.2, smooth=True, name="spout", color=chrome, sides=14)
lever = box(1.4, 9, 1.4, at=(243, 436, H + TOP + 12), name="lever", color=chrome)

# the cooktop on the left run, and the hood over it
hob = box(52, 80, 0.8, at=(4, 215, H + TOP), name="cooktop", color="#1e2024")
hob.fillet(0.3, edges="top")
rings = []
for cx, cy, r in [(18, 235, 9), (18, 275, 7), (40, 232, 7), (40, 272, 10)]:
    ring = cylinder(r, 0.1, at=(cx, cy, H + TOP + 0.8), color="#3a3f47", sides=48) - cylinder(r - 0.6, 0.1, at=(cx, cy, H + TOP + 0.8), sides=48)
    ring.paint("#3a3f47")
    ring.name = "burner"
    rings.append(ring)
hood = loft([rect(0, 210, 55, 90, offset=165), rect(0, 240, 28, 30, offset=200)], name="hood", color="#d8dadf")
chimney = box(28, 30, 70, at=(0, 240, 200), name="hood chimney", color="#d8dadf")

# ---------- wall units ----------
walls_ = []
for a0, a1 in [(0, 165), (315, 420)]:
    walls_.append(box(a1 - a0, 34, 72, at=(a0, 416, 150), name="wall unit", color="#e9e6e0"))
    k = round((a1 - a0) / 52)
    for i in range(k):
        x0 = a0 + (a1 - a0) * i / k
        x1 = a0 + (a1 - a0) * (i + 1) / k
        d = box(x1 - x0 - GAP, 2, 72 - GAP, at=(x0 + GAP / 2, 414, 150 + GAP / 2), name="front", color=front_c)
        fronts.append(group([d, handle_bar((x0 + x1) / 2, 414, 156, "x")], name=nm("door")))

# ---------- a tall unit for the fridge, at the end of the run ----------
tall = box(64, DEPTH - 2, 222, at=(422, 392, 0), name="tall unit", color="#e9e6e0")
for z0, z1 in [(10, 92), (92, 222)]:
    d = box(64 - GAP, 2, z1 - z0 - GAP, at=(422 + GAP / 2, 390, z0 + GAP / 2), name="front", color=front_c)
    bar = box(2.5, 1.2, 30, at=(428, 387.5, (z0 + 4) if z0 > 10 else z1 - 36), name="handle", color=steel)
    fronts.append(group([d, bar], name="fridge door" if z0 > 10 else "freezer door"))
units_.append(tall)

# ---------- the island and its stools ----------
island = box(200, 80, H - 10, at=(240, 160, 10), name="island", color=front_c)
island_plinth = box(190, 70, 10, at=(245, 165, 0), name="plinth", color=dark)
island_top = box(214, 100, TOP, at=(233, 150, H), name="island top", color=oak)
island_top.fillet(0.6, edges="top")
stools = []
for k in range(3):
    x = 270 + k * 70
    seat = polygon([(0, 0), (19, 0), (20, 1.5), (20, 4), (17, 5.5), (0, 6)], plane="xz").revolve(axis="z", name="seat", color=oak, sides=40)
    seat.move(x, 120, 64)
    legs = []
    for i in range(4):
        a = radians(45 + 90 * i)
        legs.append(cylinder(1.4, 66, at=(x + 15 * cos(a), 120 + 15 * sin(a), 0), axis=(-0.13 * cos(a), -0.13 * sin(a), 1), name="leg", color=dark, sides=12))
    footrest = cylinder(14, 1.4, at=(x, 120, 24), color=dark, sides=40) - cylinder(12.6, 1.4, at=(x, 120, 24), sides=40)
    footrest.paint(dark)
    footrest.name = "footrest"
    stools.append(group([seat, footrest] + legs, name=f"stool {k + 1}"))

# a bowl of oranges, a plant on the sill
bowl = polygon([(0, 0), (5, 0), (6, 1), (12, 7), (13, 9), (12.2, 9), (5.4, 1.8), (0, 1.8)], plane="xz").revolve(axis="z", name="bowl", color="#f4f2ec", sides=48)
bowl.move(300, 200, H + TOP)
fruit = [sphere(3.8, at=(300 + dx, 200 + dy, H + TOP + 5.5 + dz), name="orange", color="orange", sides=16) for dx, dy, dz in [(-3, -2, 0), (3.5, -1, 0), (0, 3.5, 0), (0, 0, 5)]]
pot = cone(7, 9, 14, at=(190, 445, 112), name="pot", color="terracotta", sides=24)
leaves = [sphere(7 - k, at=(190 + 4 * cos(k * 2.1), 445 + 3 * sin(k * 2.1), 130 + 3 * k), name="leaves", color=["#4f7d3a", "#5f8f44", "#6a9a4c"][k % 3], sides=12) for k in range(4)]

# pendant lamps over the island
lamps = []
for x in (290, 390):
    shade = polygon([(0, 0), (4, 0), (6, -2), (15, -18), (16, -20), (0, -20)], plane="xz").revolve(axis="z", name="shade", color=dark, sides=40)
    shade.shell(0.5, open="bottom")
    shade.move(x, 200, 200)
    cord = cylinder(0.4, 70, at=(x, 200, 200), name="cord", color=dark, sides=8)
    bulb = sphere(5, at=(x, 200, 185), name="bulb", color="#fff3d1", sides=20)
    lamps.append(group([shade, cord, bulb], name="pendant"))

group([floor_, back_wall, left_wall, sill] + win, name="room")
group(units_ + fronts + [worktop, basin, drain, tap_base, spout, lever, hob, hood, chimney] + rings + walls_, name="kitchen")
group([island, island_plinth, island_top], name="island")
group([bowl] + fruit, name="fruit bowl")
group([pot] + leaves, name="plant")
