from manim import *
import numpy as np
import random

class OSKVCommunity(Scene):
    def construct(self):
        # Set dark background
        self.camera.background_color = "#0a0a0f"
        
        # === PART 1: Particle Explosion Intro ===
        particles = VGroup()
        for _ in range(150):
            dot = Dot(
                point=np.array([0, 0, 0]),
                radius=random.uniform(0.02, 0.08),
                color=random.choice([BLUE, PURPLE, TEAL, WHITE, BLUE_B])
            )
            dot.set_opacity(random.uniform(0.3, 1.0))
            particles.add(dot)
        
        self.add(particles)
        
        # Explode particles outward
        animations = []
        for dot in particles:
            angle = random.uniform(0, TAU)
            distance = random.uniform(3, 8)
            end_pos = np.array([
                distance * np.cos(angle),
                distance * np.sin(angle),
                0
            ])
            animations.append(dot.animate.move_to(end_pos).set_opacity(0))
        
        self.play(*animations, run_time=1.5, rate_func=rush_from)
        self.remove(particles)
        
        # === PART 2: Neural Network Visualization ===
        # Create nodes in layers
        layer_sizes = [4, 6, 8, 6, 4]
        layers = []
        all_nodes = VGroup()
        
        for i, size in enumerate(layer_sizes):
            layer = VGroup()
            x_pos = (i - 2) * 2
            for j in range(size):
                y_pos = (j - (size - 1) / 2) * 0.8
                node = Circle(radius=0.15, color=BLUE_C, fill_opacity=0.8)
                node.move_to([x_pos, y_pos, 0])
                node.set_stroke(WHITE, width=1)
                layer.add(node)
            layers.append(layer)
            all_nodes.add(layer)
        
        # Create connections
        connections = VGroup()
        for i in range(len(layers) - 1):
            for node1 in layers[i]:
                for node2 in layers[i + 1]:
                    line = Line(
                        node1.get_center(), 
                        node2.get_center(),
                        stroke_width=0.5,
                        color=BLUE_E
                    )
                    line.set_opacity(0.3)
                    connections.add(line)
        
        # Animate network appearing
        self.play(
            LaggedStart(*[GrowFromCenter(node) for layer in layers for node in layer], lag_ratio=0.02),
            run_time=1.5
        )
        self.play(
            LaggedStart(*[Create(line) for line in connections], lag_ratio=0.005),
            run_time=1
        )
        
        # Pulse through network (data flow)
        for _ in range(2):
            pulses = []
            for i in range(len(layers) - 1):
                for node1 in layers[i]:
                    for node2 in layers[i + 1]:
                        pulse = Dot(
                            point=node1.get_center(),
                            radius=0.05,
                            color=TEAL
                        )
                        pulse.set_glow_factor(2)
                        pulses.append(pulse)
            
            pulse_group = VGroup(*pulses[:50])  # Limit for performance
            self.add(pulse_group)
            
            anims = [
                pulse.animate.move_to(
                    layers[(i % (len(layers)-1)) + 1][i % len(layers[(i % (len(layers)-1)) + 1])].get_center()
                ).set_opacity(0)
                for i, pulse in enumerate(pulse_group)
            ]
            self.play(*anims, run_time=0.8)
            self.remove(pulse_group)
        
        # Fade network
        self.play(
            FadeOut(all_nodes),
            FadeOut(connections),
            run_time=0.8
        )
        
        # === PART 3: Geometric Transformation ===
        # Sacred geometry style
        shapes = VGroup()
        
        # Outer hexagon
        hex1 = RegularPolygon(n=6, radius=2.5, color=PURPLE)
        hex1.set_stroke(width=2)
        
        # Inner hexagon (rotated)
        hex2 = RegularPolygon(n=6, radius=1.8, color=BLUE)
        hex2.rotate(PI/6)
        hex2.set_stroke(width=2)
        
        # Triangle
        tri = RegularPolygon(n=3, radius=1.2, color=TEAL)
        tri.set_stroke(width=2)
        
        # Circle in center
        circ = Circle(radius=0.6, color=WHITE)
        circ.set_stroke(width=2)
        
        shapes.add(hex1, hex2, tri, circ)
        
        self.play(
            LaggedStart(
                Create(hex1),
                Create(hex2),
                Create(tri),
                Create(circ),
                lag_ratio=0.3
            ),
            run_time=2
        )
        
        # Rotate and pulse
        self.play(
            Rotate(hex1, PI/3, about_point=ORIGIN),
            Rotate(hex2, -PI/3, about_point=ORIGIN),
            Rotate(tri, PI/2, about_point=ORIGIN),
            circ.animate.scale(1.3),
            run_time=1.5
        )
        
        # Transform into OSKV text
        oskv_text = Text("OSKV", font_size=120, weight=BOLD)
        oskv_text.set_color_by_gradient(BLUE, PURPLE, TEAL)
        
        self.play(
            ReplacementTransform(shapes, oskv_text),
            run_time=1.5
        )
        
        # === PART 4: Text Effects ===
        # Add glow effect (simulate with scaled copies)
        glow = oskv_text.copy()
        glow.set_opacity(0.3)
        glow.set_stroke(BLUE, width=10, opacity=0.5)
        self.add(glow)
        self.bring_to_front(oskv_text)
        
        # Subtitle
        subtitle = Text("THE COMMUNITY", font_size=36)
        subtitle.set_color(WHITE)
        subtitle.set_opacity(0.8)
        subtitle.next_to(oskv_text, DOWN, buff=0.5)
        
        self.play(
            FadeIn(subtitle, shift=UP * 0.3),
            run_time=0.8
        )
        
        # Floating particles around text
        ambient_particles = VGroup()
        for _ in range(40):
            p = Dot(
                radius=random.uniform(0.02, 0.05),
                color=random.choice([BLUE, PURPLE, TEAL, WHITE])
            )
            p.set_opacity(random.uniform(0.2, 0.6))
            p.move_to([
                random.uniform(-6, 6),
                random.uniform(-3.5, 3.5),
                0
            ])
            ambient_particles.add(p)
        
        self.play(
            FadeIn(ambient_particles, run_time=0.5)
        )
        
        # Gentle floating animation
        float_anims = []
        for p in ambient_particles:
            new_pos = p.get_center() + np.array([
                random.uniform(-0.5, 0.5),
                random.uniform(-0.5, 0.5),
                0
            ])
            float_anims.append(p.animate.move_to(new_pos))
        
        self.play(*float_anims, run_time=2)
        
        # Final pulse
        self.play(
            oskv_text.animate.scale(1.1),
            glow.animate.scale(1.15).set_opacity(0.5),
            rate_func=there_and_back,
            run_time=0.8
        )
        
        # Hold
        self.wait(1.5)
        
        # Fade out
        self.play(
            FadeOut(oskv_text),
            FadeOut(glow),
            FadeOut(subtitle),
            FadeOut(ambient_particles),
            run_time=1
        )


class OSKVIntro(Scene):
    """Alternative shorter intro animation"""
    def construct(self):
        self.camera.background_color = "#0a0a0f"
        
        # Circular wave rings expanding
        rings = VGroup()
        for i in range(8):
            ring = Circle(radius=0.1, color=BLUE)
            ring.set_stroke(width=3 - i * 0.3, opacity=1 - i * 0.1)
            rings.add(ring)
        
        self.add(rings)
        
        ring_anims = [
            ring.animate.scale(30).set_opacity(0)
            for ring in rings
        ]
        
        self.play(
            LaggedStart(*ring_anims, lag_ratio=0.15),
            run_time=2
        )
        
        # OSKV appears from the center
        text = Text("OSKV", font_size=144, weight=BOLD)
        text.set_color_by_gradient(BLUE, PURPLE)
        
        self.play(
            GrowFromCenter(text),
            run_time=1
        )
        
        # Underline swoosh
        underline = Line(
            start=text.get_left() + DOWN * 0.5 + LEFT * 0.5,
            end=text.get_right() + DOWN * 0.5 + RIGHT * 0.5,
            color=TEAL,
            stroke_width=4
        )
        
        self.play(Create(underline), run_time=0.6)
        
        self.wait(2)
