import blender
import bpy
import random

# Clear existing objects in the scene
bpy.ops.object.select_all(action='SELECT')
bpy.ops.object.delete(use_global=False)

# Helper function to create materials
def create_material(name, r, g, b):
    mat = bpy.data.materials.new(name=name)
    mat.use_nodes = True
    nodes = mat.node_tree.nodes
    principled = nodes.get("Principled BSDF")
    if principled:
        principled.inputs['Base Color'].default_value = (r, g, b, 1.0)
    return mat

# Create color palette
colors = {
    'road': create_material('RoadMat', 0.1, 0.1, 0.1),
    'light_b': create_material('LightB', 0.2, 0.5, 0.8),
    'dark_b': create_material('DarkB', 0.7, 0.3, 0.3),
    'yellow_b': create_material('YellowB', 0.9, 0.7, 0.2),
    'car': create_material('CarMat', 0.1, 0.6, 0.3),
    'pole': create_material('PoleMat', 0.4, 0.4, 0.4)
}

# 1. Create the Road Base
bpy.ops.mesh.primitive_plane_add(size=30, location=(0, 0, 0))
road = bpy.context.active_object
road.name = "Road_Base"
road.data.materials.append(colors['road'])

# 2. Generate 20+ Objects (Buildings, Cars, Streetlights)
obj_count = 0

# Side 1 Buildings (Left)
for i in range(6):
    h = random.uniform(4.0, 8.0)
    bpy.ops.mesh.primitive_cube_add(size=1, location=(-6, -10 + (i * 4), h/2))
    b = bpy.context.active_object
    b.name = f"Building_L_{i}"
    b.scale = (3, 3, h)
    b.data.materials.append(random.choice([colors['light_b'], colors['dark_b'], colors['yellow_b']]))
    obj_count += 1

# Side 2 Buildings (Right)
for i in range(6):
    h = random.uniform(4.0, 8.0)
    bpy.ops.mesh.primitive_cube_add(size=1, location=(6, -10 + (i * 4), h/2))
    b = bpy.context.active_object
    b.name = f"Building_R_{i}"
    b.scale = (3, 3, h)
    b.data.materials.append(random.choice([colors['light_b'], colors['dark_b'], colors['yellow_b']]))
    obj_count += 1

# Streetlights (Poles + Lamps)
for i in range(4):
    y_pos = -8 + (i * 6)
    # Pole
    bpy.ops.mesh.primitive_cylinder_add(radius=0.1, depth=3, location=(-3.5, y_pos, 1.5))
    p = bpy.context.active_object
    p.name = f"LightPole_{i}"
    p.data.materials.append(colors['pole'])
    obj_count += 1
    # Lamp head
    bpy.ops.mesh.primitive_uv_sphere_add(radius=0.2, location=(-3.5, y_pos, 3.1))
    lh = bpy.context.active_object
    lh.name = f"LampHead_{i}"
    lh.data.materials.append(colors['yellow_b'])
    obj_count += 1

# Cars scattered on the street
for i in range(4):
    bpy.ops.mesh.primitive_cube_add(size=1, location=(random.uniform(-1.5, 1.5), -12 + (i * 7), 0.4))
    car = bpy.context.active_object
    car.name = f"Car_{i}"
    car.scale = (1.2, 2.2, 0.7)
    car.rotation_euler = (0, 0, random.uniform(-0.1, 0.1))
    car.data.materials.append(colors['car'])
    obj_count += 1

# 3. Lights + Shadows Setup
bpy.ops.object.light_add(type='SUN', radius=1, location=(5, -5, 12))
sun = bpy.context.active_object
sun.name = "Main_Sun"
sun.data.energy = 4.0
sun.data.use_shadow = True
sun.rotation_euler = (0.6, 0.4, 0.2)

# 4. Camera Setup
bpy.ops.object.camera_add(location=(0, -18, 5))
cam = bpy.context.active_object
cam.name = "Scene_Camera"
cam.rotation_euler = (1.35, 0, 0) # Tilted downward slightly to look down the street
bpy.context.scene.camera = cam

print(f"Generated {obj_count} objects dynamically with colors, lights, and a camera.")
