"""
Track 02: U SAVED ME - Particles Coalescing into Sacred Geometry (Icosahedron)
"""

import bpy
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 get_icosahedron_vertices(scale=2.5):
    """Get icosahedron vertex positions."""
    phi = (1 + math.sqrt(5)) / 2  # Golden ratio
    
    verts = [
        [0, 1, phi], [0, -1, phi], [0, 1, -phi], [0, -1, -phi],
        [1, phi, 0], [-1, phi, 0], [1, -phi, 0], [-1, -phi, 0],
        [phi, 0, 1], [-phi, 0, 1], [phi, 0, -1], [-phi, 0, -1]
    ]
    
    # Normalize and scale
    result = []
    for v in verts:
        norm = math.sqrt(sum(x*x for x in v))
        result.append([x / norm * scale for x in v])
    
    return result


def get_icosahedron_edges():
    """Get icosahedron edge pairs."""
    return [
        (0, 1), (0, 4), (0, 5), (0, 8), (0, 9),
        (1, 6), (1, 7), (1, 8), (1, 9),
        (2, 3), (2, 4), (2, 5), (2, 10), (2, 11),
        (3, 6), (3, 7), (3, 10), (3, 11),
        (4, 5), (4, 8), (4, 10),
        (5, 9), (5, 11),
        (6, 7), (6, 8), (6, 10),
        (7, 9), (7, 11),
        (8, 10), (9, 11)
    ]


def create_sacred_geometry_animation():
    """Create the full Track 02 animation."""
    clear_scene()
    setup_scene(background_color=(0.04, 0.08, 0.16, 1.0))  # Dark blue
    
    # Create camera
    camera = create_camera(location=(0, -12, 6), rotation=(1.1, 0, 0))
    animate_camera_orbit(camera, center=(0, 0, 0), radius=12, height=5,
                        start_frame=1, end_frame=TOTAL_FRAMES, revolutions=0.4)
    
    # Get target positions (icosahedron vertices)
    target_positions = get_icosahedron_vertices(scale=2.5)
    
    # Add midpoints for more particles
    for i, v1 in enumerate(target_positions):
        for v2 in target_positions[i+1:]:
            mid = [(v1[j] + v2[j]) / 2 for j in range(3)]
            norm = math.sqrt(sum(x*x for x in mid))
            if norm > 0.5:
                target_positions.append([x / norm * 2.5 for x in mid])
    
    # Limit to 60 particles
    target_positions = target_positions[:60]
    
    # Create particles
    particles = []
    mat = create_emission_material("ParticleMat", COLORS["u_saved_me"], strength=3.0)
    
    for i, target in enumerate(target_positions):
        # Random start position (scattered)
        start = [random.uniform(-8, 8) for _ in range(3)]
        
        bpy.ops.mesh.primitive_ico_sphere_add(radius=0.12, subdivisions=2, location=start)
        particle = bpy.context.active_object
        particle.name = f"Particle_{i:03d}"
        particle.data.materials.append(mat)
        particles.append((particle, start, target))
    
    # Animate particles coalescing
    coalesce_start = 60
    coalesce_end = 300
    
    for particle, start, target in particles:
        # Start position
        keyframe_location(particle, 1, start)
        keyframe_location(particle, coalesce_start, start)
        
        # End position (at icosahedron vertex)
        keyframe_location(particle, coalesce_end, target)
        keyframe_location(particle, TOTAL_FRAMES - 30, target)
        
        # Set easing
        if particle.animation_data:
            for fc in particle.animation_data.action.fcurves:
                for kf in fc.keyframe_points:
                    kf.interpolation = 'BEZIER'
                    kf.easing = 'EASE_IN_OUT'
    
    # Create edges after particles arrive
    edges = []
    edge_pairs = get_icosahedron_edges()
    edge_mat = create_emission_material("EdgeMat", COLORS["u_saved_me"], strength=1.5)
    
    verts = get_icosahedron_vertices(scale=2.5)
    
    for i, (v1_idx, v2_idx) in enumerate(edge_pairs):
        v1 = verts[v1_idx]
        v2 = verts[v2_idx]
        
        # Create curve for edge
        curve_data = bpy.data.curves.new(name=f"Edge_{i}", type='CURVE')
        curve_data.dimensions = '3D'
        curve_data.bevel_depth = 0.02
        
        spline = curve_data.splines.new('BEZIER')
        spline.bezier_points.add(1)
        spline.bezier_points[0].co = v1
        spline.bezier_points[1].co = v2
        
        curve_obj = bpy.data.objects.new(f"Edge_{i}", curve_data)
        bpy.context.collection.objects.link(curve_obj)
        curve_obj.data.materials.append(edge_mat)
        
        # Animate edge appearance (bevel depth)
        curve_data.bevel_depth = 0.0
        curve_data.keyframe_insert(data_path="bevel_depth", frame=coalesce_end)
        curve_data.keyframe_insert(data_path="bevel_depth", frame=coalesce_end + 30)
        
        curve_data.bevel_depth = 0.02
        curve_data.keyframe_insert(data_path="bevel_depth", frame=coalesce_end + 90)
        
        edges.append(curve_obj)
    
    # Pulse effect (scale all particles)
    pulse_frames = [400, 450, 500, 550]
    for frame in pulse_frames:
        for particle, _, _ in particles:
            keyframe_scale(particle, frame, 1.0)
            keyframe_scale(particle, frame + 15, 1.4)
            keyframe_scale(particle, frame + 30, 1.0)
    
    return particles, edges


if __name__ == "__main__":
    create_sacred_geometry_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", "track02_u_saved_me.blend"))
    
    bpy.ops.export_scene.gltf(
        filepath=os.path.join(output_dir, "exports", "track02_u_saved_me.gltf"),
        export_animations=True,
        export_format='GLTF_SEPARATE'
    )
    
    bpy.ops.wm.alembic_export(
        filepath=os.path.join(output_dir, "exports", "track02_u_saved_me.abc"),
        start=1, end=TOTAL_FRAMES
    )
    
    print("Track 02 - U Saved Me: Export complete!")
