"""
Track 03: NOTHING - Sphere Explosion/Fragmentation into Void
"""

import bpy
import bmesh
import math
import random
import sys
import os

sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from utils import *


def create_fragments(count=60, sphere_radius=2.0):
    """Create fragment particles from a sphere."""
    fragments = []
    mat = create_emission_material("FragmentMat", COLORS["nothing"], strength=1.0)
    
    for i in range(count):
        # Random position within sphere
        theta = random.uniform(0, 2 * math.pi)
        phi = random.uniform(0, math.pi)
        r = random.uniform(0, sphere_radius * 0.9)
        
        x = r * math.sin(phi) * math.cos(theta)
        y = r * math.sin(phi) * math.sin(theta)
        z = r * math.cos(phi)
        
        size = random.uniform(0.15, 0.4)
        
        bpy.ops.mesh.primitive_ico_sphere_add(
            radius=size, 
            subdivisions=1, 
            location=(x, y, z)
        )
        frag = bpy.context.active_object
        frag.name = f"Fragment_{i:03d}"
        frag.data.materials.append(mat)
        
        # Store explosion direction
        if r > 0.1:
            direction = (x/r, y/r, z/r)
        else:
            direction = (random.uniform(-1, 1), random.uniform(-1, 1), random.uniform(-1, 1))
            norm = math.sqrt(sum(d*d for d in direction))
            direction = tuple(d/norm for d in direction)
        
        fragments.append((frag, (x, y, z), direction))
    
    return fragments


def create_nothing_animation():
    """Create the full Track 03 animation."""
    clear_scene()
    setup_scene(background_color=(0.04, 0.04, 0.04, 1.0))  # Near black
    
    # Create camera
    camera = create_camera(location=(0, -10, 4), rotation=(1.15, 0, 0))
    animate_camera_orbit(camera, center=(0, 0, 0), radius=10, height=4,
                        start_frame=1, end_frame=TOTAL_FRAMES, revolutions=0.3)
    
    # Create initial sphere
    sphere = create_sphere(location=(0, 0, 0), radius=2.0, segments=32, rings=16, name="MainSphere")
    sphere_mat = create_emission_material("SphereMat", COLORS["nothing"], strength=1.2)
    sphere.data.materials.append(sphere_mat)
    
    # Animate sphere appearance
    keyframe_scale(sphere, 1, 0.01)
    keyframe_scale(sphere, 60, 1.0)
    keyframe_scale(sphere, 90, 1.0)
    
    # Explosion at frame 120
    explosion_frame = 120
    
    # Sphere disappears at explosion
    keyframe_scale(sphere, explosion_frame - 1, 1.0)
    keyframe_scale(sphere, explosion_frame, 0.01)
    
    # Create fragments
    fragments = create_fragments(count=60, sphere_radius=2.0)
    
    # Animate fragments
    for frag, start_pos, direction in fragments:
        # Start invisible
        keyframe_scale(frag, 1, 0.01)
        keyframe_scale(frag, explosion_frame - 1, 0.01)
        
        # Appear at explosion
        keyframe_scale(frag, explosion_frame, 1.0)
        keyframe_location(frag, explosion_frame, start_pos)
        
        # Drift outward into void
        drift_distance = random.uniform(6, 12)
        end_pos = tuple(start_pos[i] + direction[i] * drift_distance for i in range(3))
        
        # Animate drift
        keyframe_location(frag, TOTAL_FRAMES, end_pos)
        
        # Fade out (scale down)
        keyframe_scale(frag, TOTAL_FRAMES - 60, 0.6)
        keyframe_scale(frag, TOTAL_FRAMES, 0.1)
        
        # Set linear interpolation for drift
        if frag.animation_data:
            for fc in frag.animation_data.action.fcurves:
                for kf in fc.keyframe_points:
                    kf.interpolation = 'LINEAR'
    
    # Add some ambient dust particles
    dust = []
    dust_mat = create_emission_material("DustMat", COLORS["nothing"], strength=0.3)
    
    for i in range(40):
        pos = [random.uniform(-6, 6) for _ in range(3)]
        bpy.ops.mesh.primitive_ico_sphere_add(radius=0.05, subdivisions=0, location=pos)
        d = bpy.context.active_object
        d.name = f"Dust_{i:03d}"
        d.data.materials.append(dust_mat)
        
        # Slow random drift
        end_pos = [pos[j] + random.uniform(-2, 2) for j in range(3)]
        keyframe_location(d, 1, pos)
        keyframe_location(d, TOTAL_FRAMES, end_pos)
        
        dust.append(d)
    
    return sphere, fragments, dust


if __name__ == "__main__":
    create_nothing_animation()
    
    output_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    bpy.ops.wm.save_as_mainfile(filepath=os.path.join(output_dir, "exports", "track03_nothing.blend"))
    
    bpy.ops.export_scene.gltf(
        filepath=os.path.join(output_dir, "exports", "track03_nothing.gltf"),
        export_animations=True,
        export_format='GLTF_SEPARATE'
    )
    
    bpy.ops.wm.alembic_export(
        filepath=os.path.join(output_dir, "exports", "track03_nothing.abc"),
        start=1, end=TOTAL_FRAMES
    )
    
    print("Track 03 - Nothing: Export complete!")
