"""
Track 08: IDK - Lorenz Attractor with Trailing Particle
"""

import bpy
import math
import sys
import os

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


def generate_lorenz_points(num_points=8000, scale=0.12):
    """Generate points along a Lorenz attractor."""
    sigma, rho, beta = 10, 28, 8/3
    dt = 0.005
    
    x, y, z = 0.1, 0, 0
    points = []
    
    for _ in range(num_points):
        dx = sigma * (y - x) * dt
        dy = (x * (rho - z) - y) * dt
        dz = (x * y - beta * z) * dt
        
        x += dx
        y += dy
        z += dz
        
        points.append((x * scale, y * scale, (z - 25) * scale))
    
    return points


def create_idk_animation():
    """Create the full Track 08 animation."""
    clear_scene()
    setup_scene(background_color=(0.12, 0.04, 0.18, 1.0))  # Dark purple
    
    # Create camera
    camera = create_camera(location=(0, -12, 5), rotation=(1.15, 0, 0))
    animate_camera_orbit(camera, center=(0, 0, 0), radius=12, height=5,
                        start_frame=1, end_frame=TOTAL_FRAMES, revolutions=0.5)
    
    # Generate Lorenz attractor points
    points = generate_lorenz_points(num_points=8000, scale=0.12)
    
    # Create curve from points (sample every 4th point for performance)
    sampled_points = points[::4]
    
    curve_data = bpy.data.curves.new(name="LorenzCurve", type='CURVE')
    curve_data.dimensions = '3D'
    curve_data.bevel_depth = 0.015
    curve_data.bevel_resolution = 4
    
    spline = curve_data.splines.new('NURBS')
    spline.points.add(len(sampled_points) - 1)
    
    for i, point in enumerate(sampled_points):
        spline.points[i].co = (point[0], point[1], point[2], 1)
    
    spline.use_endpoint_u = True
    spline.order_u = 4
    
    attractor = bpy.data.objects.new("LorenzAttractor", curve_data)
    bpy.context.collection.objects.link(attractor)
    
    # Add material
    mat = create_emission_material("LorenzMat", COLORS["idk"], strength=2.0)
    attractor.data.materials.append(mat)
    
    # Animate the curve drawing (using bevel factor)
    curve_data.bevel_factor_start = 0.0
    curve_data.bevel_factor_end = 0.0
    curve_data.keyframe_insert(data_path="bevel_factor_end", frame=1)
    
    curve_data.bevel_factor_end = 1.0
    curve_data.keyframe_insert(data_path="bevel_factor_end", frame=450)
    
    # Set linear interpolation for smooth drawing
    if curve_data.animation_data:
        for fc in curve_data.animation_data.action.fcurves:
            for kf in fc.keyframe_points:
                kf.interpolation = 'LINEAR'
    
    # Create trailing particle
    bpy.ops.mesh.primitive_ico_sphere_add(radius=0.15, subdivisions=2, location=points[0])
    particle = bpy.context.active_object
    particle.name = "TrailingParticle"
    
    particle_mat = create_emission_material("ParticleMat", COLORS["white"], strength=5.0)
    particle.data.materials.append(particle_mat)
    
    # Animate particle along the last portion of the attractor
    particle_start_frame = 460
    particle_points = points[-200:]
    frames_per_point = max(1, (TOTAL_FRAMES - particle_start_frame - 30) // len(particle_points))
    
    # Hide particle initially
    keyframe_scale(particle, 1, 0.01)
    keyframe_scale(particle, particle_start_frame - 1, 0.01)
    keyframe_scale(particle, particle_start_frame, 1.0)
    
    for i, point in enumerate(particle_points):
        frame = particle_start_frame + i * frames_per_point
        if frame <= TOTAL_FRAMES - 30:
            keyframe_location(particle, frame, point)
    
    # Add some chaos visualization - secondary attractor trails
    colors = [
        (0.8, 0.35, 0.6, 1.0),  # Lighter pink
        (0.6, 0.25, 0.5, 1.0),  # Darker pink
    ]
    
    for idx, color in enumerate(colors):
        # Generate with slightly different initial conditions
        alt_points = []
        x, y, z = 0.1 + idx * 0.01, 0.01 * idx, 0.01 * idx
        sigma, rho, beta = 10, 28, 8/3
        dt = 0.005
        
        for _ in range(6000):
            dx = sigma * (y - x) * dt
            dy = (x * (rho - z) - y) * dt
            dz = (x * y - beta * z) * dt
            x += dx
            y += dy
            z += dz
            alt_points.append((x * 0.12, y * 0.12, (z - 25) * 0.12))
        
        # Create secondary curve
        alt_sampled = alt_points[::6]
        
        alt_curve_data = bpy.data.curves.new(name=f"LorenzAlt_{idx}", type='CURVE')
        alt_curve_data.dimensions = '3D'
        alt_curve_data.bevel_depth = 0.008
        
        alt_spline = alt_curve_data.splines.new('NURBS')
        alt_spline.points.add(len(alt_sampled) - 1)
        
        for i, point in enumerate(alt_sampled):
            alt_spline.points[i].co = (point[0], point[1], point[2], 1)
        
        alt_spline.use_endpoint_u = True
        
        alt_attractor = bpy.data.objects.new(f"LorenzAlt_{idx}", alt_curve_data)
        bpy.context.collection.objects.link(alt_attractor)
        
        alt_mat = create_emission_material(f"LorenzAltMat_{idx}", color, strength=1.0)
        alt_attractor.data.materials.append(alt_mat)
        
        # Animate drawing
        alt_curve_data.bevel_factor_end = 0.0
        alt_curve_data.keyframe_insert(data_path="bevel_factor_end", frame=1)
        
        alt_curve_data.bevel_factor_end = 1.0
        alt_curve_data.keyframe_insert(data_path="bevel_factor_end", frame=400 + idx * 30)
    
    return attractor, particle


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