"""Restaurant: decor props for the 3D bridge.

After assets/story/intro/07_kitchen_single.png: a shelf of plates, a rail of
hanging pans and ladles, framed pictures, a clock, a chalk menu and wall lamps
for the inside; rooftop units and street furniture for the outside.

Wall pieces are modelled against their wall: the back plane is y = 0 and the
piece stands out toward -Y (glTF +Z, the room side of the north wall), origin at
the back, bottom centre. Nodes named "Glow" receive an emissive material.

Reuses the mesh helpers of crater_meadow_props.py.

Run headless from big-egg-3d/:
  blender --background --factory-startup --python tools/blender/restaurant_props.py [-- --only name,name]
"""
import bpy, bmesh, math, os, random, sys
from mathutils import Vector, Matrix

sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
import crater_meadow_props as kit  # noqa: E402
from crater_meadow_props import srgb, mix, ico, cyl, bar, build, paint  # noqa: E402

kit.OUT = os.path.join(kit.PROJECT, "assets", "models", "restaurant_dressing")


def box(size, at=(0, 0, 0)):
    bm = bmesh.new()
    bmesh.ops.create_cube(bm, size=1.0)
    bmesh.ops.scale(bm, vec=Vector(size), verts=bm.verts)
    bmesh.ops.translate(bm, vec=Vector(at), verts=bm.verts)
    return bm


def flat(hexa, light=None, dark=None, vary=0.0, seed=0):
    return paint(srgb(hexa), srgb(light) if light else None, srgb(dark) if dark else None, vary, seed, 0.5)


def disc_y(radius, depth, at, segs=20):
    """A disc facing -Y (toward the room)."""
    return cyl(radius, radius, depth, segs, at, Matrix.Rotation(math.pi / 2, 3, "X"))


# ---------------------------------------------------------------- inside

def shelf_plates(name, seed):
    r = random.Random(seed)
    wood = flat("#6b4a31", "#8c6546", "#3a281a", 0.1, seed)
    parts = [(box((1.3, 0.22, 0.04), (0, -0.11, 0.0)), wood)]
    for x in (-0.5, 0.5):
        parts.append((box((0.03, 0.18, 0.14), (x, -0.09, -0.08)), flat("#2d2d2f", "#5a5a5e", "#141415")))
    white = flat("#e7e3da", "#ffffff", "#9a968e")
    x = -0.58
    while x < 0.58:
        kind = r.randint(0, 3)
        if kind == 0:  # stack of plates
            for k in range(r.randint(3, 6)):
                parts.append((cyl(0.1, 0.1, 0.012, 16, (x, -0.11, 0.02 + k * 0.014)), white))
            x += 0.24
        elif kind == 1:  # bowls
            parts.append((cyl(0.06, 0.08, 0.06, 14, (x, -0.11, 0.02)), flat("#d9d3c4", "#f2eee4", "#8a857a")))
            x += 0.2
        elif kind == 2:  # jar
            tone = r.choice(["#b88a3c", "#8c3b2a", "#6c7d3c", "#c9b27a"])
            parts.append((cyl(0.045, 0.045, 0.13, 12, (x, -0.11, 0.02)), flat(tone, None, None, 0.1, seed)))
            parts.append((cyl(0.048, 0.048, 0.02, 12, (x, -0.11, 0.15)), flat("#8b8f93", "#c3c6c8", "#4a4c4f")))
            x += 0.14
        else:  # upright plate leaning on the wall
            parts.append((disc_y(0.11, 0.012, (x, -0.03, 0.13)), white))
            x += 0.2
    return build(name, parts)


def utensil_rail(name, seed):
    steel = flat("#9ea3a8", "#dfe3e6", "#4b4e52")
    iron = flat("#2a2a2c", "#55555a", "#101011")
    parts = [(bar((-0.55, -0.06, 0), (0.55, -0.06, 0), 0.012), steel)]
    for x in (-0.55, 0.55):
        parts.append((bar((x, 0, 0), (x, -0.06, 0), 0.01), steel))
    # The frying pan: the game's own weapon, hung pride of place.
    parts.append((bar((-0.22, -0.06, 0), (-0.22, -0.06, -0.3), 0.012), iron))
    parts.append((disc_y(0.17, 0.03, (-0.22, -0.05, -0.47)), iron))
    parts.append((cyl(0.2, 0.2, 0.005, 20, (-0.22, -0.035, -0.47), Matrix.Rotation(math.pi / 2, 3, "X")), iron))
    # Ladle, spatula, whisk, small pot.
    parts.append((bar((0.05, -0.06, 0), (0.05, -0.06, -0.3), 0.008), steel))
    parts.append((ico(0.05, 1, (0.05, -0.07, -0.33), (1, 1, 0.6)), steel))
    parts.append((bar((0.18, -0.06, 0), (0.18, -0.06, -0.26), 0.008), flat("#3b2c22")))
    parts.append((box((0.07, 0.01, 0.1), (0.18, -0.06, -0.31)), steel))
    parts.append((bar((0.31, -0.06, 0), (0.31, -0.06, -0.12), 0.008), steel))
    parts.append((ico(0.045, 1, (0.31, -0.06, -0.19), (1, 1, 1.6)), steel))
    parts.append((bar((0.45, -0.06, 0), (0.45, -0.06, -0.1), 0.006), steel))
    parts.append((cyl(0.08, 0.08, 0.1, 16, (0.45, -0.1, -0.24)), flat("#b86b3a", "#e0955c", "#5a3017")))
    return build(name, parts)


def picture(name, seed, art):
    frame = flat("#5a3b24", "#7d5637", "#2a1b10")
    parts = [(box((0.56, 0.03, 0.44), (0, -0.015, 0.22)), frame)]
    canvas_at = (0, -0.032, 0.22)
    parts.append((box((0.48, 0.005, 0.36), canvas_at), art[0]))
    for shape in art[1:]:
        parts.append(shape)
    return build(name, parts)


def frame_egg(name, seed):
    sky = flat("#5f7f96", "#7d9bb0", "#3b5263")
    egg = ico(0.1, 2, (0, -0.04, 0.2), (0.8, 0.1, 1.05))
    return picture(name, seed, [sky, (egg, flat("#efe9dc", "#ffffff", "#b5ad9d"))])


def frame_landscape(name, seed):
    field = flat("#6f7d4a", "#8e9a62", "#3f4a2a")
    sky = box((0.48, 0.004, 0.14), (0, -0.036, 0.33))
    sun = disc_y(0.04, 0.004, (0.14, -0.04, 0.34), 12)
    return picture(name, seed, [field, (sky, flat("#a9bcc4", "#c9d8de")), (sun, flat("#e8c56a", "#fff0b0"))])


def frame_poster(name, seed):
    red = flat("#9c2f2a", "#c4524a", "#4f1714")
    band = box((0.48, 0.004, 0.08), (0, -0.036, 0.12))
    dot = disc_y(0.08, 0.004, (0, -0.04, 0.27), 16)
    return picture(name, seed, [red, (band, flat("#e8dcc0")), (dot, flat("#e8c56a", "#fff0b0"))])


def wall_clock(name, seed):
    # Case from the wall to y = -0.04, the dial just proud of it.
    parts = [(disc_y(0.18, 0.04, (0, 0.0, 0.18), 24), flat("#2a2a2c", "#55555a", "#101011")),
             (disc_y(0.155, 0.008, (0, -0.04, 0.18), 24), flat("#ece6d8", "#ffffff", "#b5ad9d"))]
    hand = flat("#1a1a1a")
    parts.append((box((0.012, 0.004, 0.11), (0, -0.052, 0.225)), hand))
    parts.append((box((0.08, 0.004, 0.012), (0.035, -0.052, 0.18)), hand))
    for k in range(12):
        a = 2 * math.pi * k / 12
        parts.append((box((0.012, 0.004, 0.025), (math.sin(a) * 0.13, -0.051, 0.18 + math.cos(a) * 0.13)), hand))
    return build(name, parts)


def chalkboard(name, seed):
    r = random.Random(seed)
    parts = [(box((0.95, 0.03, 0.65), (0, -0.015, 0.325)), flat("#5a3b24", "#7d5637", "#2a1b10")),
             (box((0.87, 0.006, 0.57), (0, -0.033, 0.325)), flat("#232a26", "#323b36", "#141816"))]
    chalk = flat("#d9d6cc", "#f0ede4")
    parts.append((box((0.36, 0.004, 0.05), (0, -0.038, 0.55)), chalk))  # the heading
    z = 0.45
    while z > 0.1:
        w = r.uniform(0.3, 0.55)
        parts.append((box((w, 0.004, 0.022), (-0.36 + w / 2, -0.038, z)), chalk))
        parts.append((box((0.08, 0.004, 0.022), (0.33, -0.038, z)), flat("#e8c56a")))
        z -= 0.075
    return build(name, parts)


def sconce(name, seed):
    brass = flat("#9c7b3c", "#d4b06a", "#4d3b19")
    obj = build(name, [(box((0.1, 0.02, 0.16), (0, -0.01, 0.0)), brass),
                       (bar((0, -0.02, 0.0), (0, -0.14, 0.05), 0.012), brass)])
    glow = build("Glow", [(cyl(0.09, 0.05, 0.12, 14, (0, -0.16, 0.02)), flat("#ffe2a8", "#fff4d6", "#e0a860"))])
    glow.parent = obj
    return obj, [glow]


# ---------------------------------------------------------------- outside

def ac_unit(name, seed):
    body = flat("#9a9c9e", "#c9cbcc", "#4d4f51", 0.08, seed)
    parts = [(box((1.0, 0.8, 0.6), (0, 0, 0.3)), body),
             (cyl(0.3, 0.3, 0.02, 20, (0.18, 0, 0.6)), flat("#2b2c2e", "#4a4b4e")),
             (box((0.5, 0.08, 0.08), (-0.2, 0.44, 0.1)), flat("#6d6f71"))]
    for k in range(5):
        parts.append((box((0.02, 0.62, 0.02), (0.18 - 0.24 + k * 0.12, 0, 0.615)), flat("#8a8c8e")))
    return build(name, parts)


def roof_vent(name, seed):
    metal = flat("#7d8084", "#b3b6b9", "#3c3e41")
    return build(name, [(cyl(0.12, 0.12, 0.45, 12), metal), (cyl(0.26, 0.05, 0.14, 12, (0, 0, 0.45)), metal)])


def chimney(name, seed):
    return build(name, [(box((0.6, 0.6, 1.1), (0, 0, 0.55)), flat("#6e3829", "#8a4a38", "#3a1c14", 0.15, seed)),
                        (box((0.7, 0.7, 0.08), (0, 0, 1.12)), flat("#5a5a5a", "#7a7a7a", "#2a2a2a")),
                        (box((0.4, 0.4, 0.02), (0, 0, 1.17)), flat("#111111"))])


def street_lamp(name, seed):
    green = flat("#2f3d36", "#4a5c52", "#141c18")
    obj = build(name, [(cyl(0.09, 0.07, 0.4, 10), green), (cyl(0.05, 0.045, 4.2, 10, (0, 0, 0.4)), green),
                       (bar((0, 0, 4.5), (0, -0.7, 4.65), 0.04, 8), green),
                       (cyl(0.2, 0.08, 0.16, 12, (0, -0.8, 4.52)), green)])
    glow = build("Glow", [(cyl(0.16, 0.16, 0.05, 12, (0, -0.8, 4.48)), flat("#ffe2a8", "#fff4d6", "#e0a860"))])
    glow.parent = obj
    return obj, [glow]


def hydrant(name, seed):
    red = flat("#a8322b", "#d65a4f", "#4a1512")
    return build(name, [(cyl(0.14, 0.14, 0.08, 12), red), (cyl(0.11, 0.1, 0.5, 12, (0, 0, 0.08)), red),
                        (ico(0.11, 1, (0, 0, 0.6), (1, 1, 0.7)), red),
                        (bar((-0.18, 0, 0.42), (0.18, 0, 0.42), 0.05, 8), red)])


def trash_can(name, seed):
    green = flat("#3c5146", "#5b7466", "#1b2620", 0.1, seed)
    return build(name, [(cyl(0.26, 0.22, 0.85, 14), green), (cyl(0.28, 0.28, 0.06, 14, (0, 0, 0.85)), flat("#2e3f36", "#4a5f53"))])


def manhole(name, seed):
    iron = flat("#2c2b2a", "#4e4c49", "#141312")
    parts = [(cyl(0.38, 0.38, 0.015, 24), iron)]
    for k in range(4):
        parts.append((cyl(0.3 - k * 0.07, 0.3 - k * 0.07, 0.02, 24, (0, 0, 0.0)), flat("#3b3a38" if k % 2 else "#252423")))
    return build(name, parts)


PROPS = {
    "shelf_plates": lambda: shelf_plates("shelf_plates", 1),
    "utensil_rail": lambda: utensil_rail("utensil_rail", 2),
    "frame_egg": lambda: frame_egg("frame_egg", 3),
    "frame_landscape": lambda: frame_landscape("frame_landscape", 4),
    "frame_poster": lambda: frame_poster("frame_poster", 5),
    "wall_clock": lambda: wall_clock("wall_clock", 6),
    "chalkboard": lambda: chalkboard("chalkboard", 7),
    "sconce": lambda: sconce("sconce", 8),
    "ac_unit": lambda: ac_unit("ac_unit", 9),
    "roof_vent": lambda: roof_vent("roof_vent", 10),
    "chimney": lambda: chimney("chimney", 11),
    "street_lamp": lambda: street_lamp("street_lamp", 12),
    "hydrant": lambda: hydrant("hydrant", 13),
    "trash_can": lambda: trash_can("trash_can", 14),
    "manhole": lambda: manhole("manhole", 15),
}

if __name__ == "__main__":
    args = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
    only = args[args.index("--only") + 1].split(",") if "--only" in args else list(PROPS)
    bpy.ops.wm.read_factory_settings(use_empty=True)
    os.makedirs(kit.OUT, exist_ok=True)
    for key in only:
        made = PROPS[key]()
        obj, extra = made if isinstance(made, tuple) else (made, [])
        kit.export(obj, extra)
