from manim import *
import numpy as np

# Color Palette — Classic 3B1B
BG = "#1C1C1C"
PRIMARY = "#58C4DD"      # BLUE — notation, labels
SECONDARY = "#83C167"    # GREEN — geometry, circles
ACCENT = "#FFFF00"       # YELLOW — highlights
RED_C = "#FF6B6B"        # RED — e constant
ORANGE = "#FFA07A"      # ORANGE — i (imaginary)
PURPLE = "#C792EA"       # PURPLE — π
MONO = "Menlo"

# Timing constants
FAST = 0.8; NORMAL = 1.5; SLOW = 2.5


class Scene1_Title(Scene):
    def construct(self):
        self.camera.background_color = BG

        title = Text(
            "The Most Beautiful Equation\nin Mathematics",
            font_size=52,
            color=PRIMARY,
            weight=BOLD,
            font=MONO,
            line_spacing=1.4
        )
        title.move_to(UP * 0.5)

        subtitle = MathTex(r"e^{i\pi} + 1 = 0", font_size=72)
        subtitle.set_color(ACCENT)
        subtitle.move_to(DOWN * 1.2)

        tagline = Text(
            "Five numbers. One line. Everything connected.",
            font_size=22,
            color=WHITE,
            font=MONO,
            opacity=0.6
        )
        tagline.move_to(DOWN * 2.5)

        self.add_subcaption("Five numbers. One line. Everything connected.", duration=3)
        self.play(FadeIn(title, run_time=SLOW), run_time=SLOW)
        self.wait(1.5)
        self.play(Write(subtitle), run_time=SLOW)
        self.wait(1.0)
        self.add_subcaption("e to the i pi plus one equals zero", duration=3)
        self.play(FadeIn(tagline), run_time=NORMAL)
        self.wait(3.0)
        self.play(FadeOut(Group(*self.mobjects)), run_time=0.5)


class Scene2_FiveConstants(Scene):
    def construct(self):
        self.camera.background_color = BG

        header = Text("Meet the Five Constants", font_size=36, color=WHITE, font=MONO, weight=BOLD)
        header.to_edge(UP, buff=0.6)
        self.add(header)

        constants_data = [
            (r"e", RED_C, "The base of\nnatural growth",  -5.0),
            (r"i", ORANGE, "The square root\nof negative one", -2.5),
            (r"\pi", PURPLE, "Ratio of a circle's\ncircumference to diameter", 0.0),
            (r"1", PRIMARY, "The foundation\nof counting",  2.5),
            (r"0", WHITE, "The concept\nof nothingness",  5.0),
        ]

        groups = []
        for sym, color, desc, x in constants_data:
            group = VGroup()
            sym_text = MathTex(sym, font_size=80, color=color)
            desc_text = Text(desc, font_size=16, color=WHITE, font=MONO, opacity=0.7, line_spacing=1.3)
            desc_text.next_to(sym_text, DOWN, buff=0.4)
            group.add(sym_text, desc_text)
            group.move_to(x * RIGHT)
            group.shift(DOWN * 0.3)
            groups.append(group)

        self.add_subcaption("Five constants. Each one fundamental.", duration=3)
        for i, g in enumerate(groups):
            self.play(FadeIn(g, run_time=NORMAL), run_time=NORMAL)
            self.wait(1.5)

        self.wait(2.0)

        teaser = Text(
            "What if I told you they were all... the same thing?",
            font_size=26,
            color=ACCENT,
            font=MONO,
        )
        teaser.to_edge(DOWN, buff=1.0)
        self.add_subcaption("What if I told you they were all the same thing?", duration=3)
        self.play(Write(teaser), run_time=SLOW)
        self.wait(3.0)
        self.play(FadeOut(Group(*self.mobjects)), run_time=0.5)


class Scene3_ComplexPlane(Scene):
    def construct(self):
        self.camera.background_color = BG

        title = Text("The Complex Plane", font_size=38, color=WHITE, font=MONO, weight=BOLD)
        title.to_edge(UP, buff=0.6)
        self.add(title)

        # Axes
        axes = Axes(
            x_range=[-2, 2, 1],
            y_range=[-2, 2, 1],
            x_length=7,
            y_length=5,
            axis_config={"include_numbers": False, "stroke_opacity": 0.5},
        )
        axes.shift(DOWN * 0.3)

        real_label = Text("Re", font_size=24, color=PRIMARY, font=MONO)
        real_label.next_to(axes.get_x_axis(), RIGHT, buff=0.3)

        imag_label = Text("Im", font_size=24, color=ORANGE, font=MONO)
        imag_label.next_to(axes.get_y_axis(), UP, buff=0.3)

        self.add_subcaption("A geometric map of numbers", duration=2)
        self.play(Create(axes), run_time=NORMAL)
        self.play(Write(real_label), Write(imag_label), run_time=FAST)
        self.wait(1.5)

        # Unit circle
        unit_circle = Circle(radius=2, stroke_color=SECONDARY, stroke_opacity=0.6, fill_opacity=0)
        unit_circle.move_to(axes.c2p(0, 0))
        self.add_subcaption("Every point on this circle encodes a rotation", duration=3)
        self.play(Create(unit_circle), run_time=SLOW)
        self.wait(1.5)

        # Label "1" at the rightmost point
        one_marker = MathTex(r"1", font_size=28, color=PRIMARY)
        one_marker.move_to(axes.c2p(1.15, 0.15))
        self.play(Write(one_marker), run_time=FAST)
        self.wait(0.5)

        # Point at (1, 0)
        p_dot = Dot(color=ACCENT, radius=0.08)
        p_dot.move_to(axes.c2p(1, 0))

        # Angle arc theta
        theta_tracker = ValueTracker(0)
        arc = Arc(radius=0.5, start_angle=0, angle=0, arc_center=axes.c2p(0, 0),
                  color=SECONDARY, stroke_width=2)

        def update_arc(m):
            angle = theta_tracker.get_value()
            m.become(Arc(radius=0.7, start_angle=0, angle=angle,
                         arc_center=axes.c2p(0, 0), color=SECONDARY, stroke_width=2.5))

        arc.add_updater(update_arc)

        # Cos/Sin labels that appear
        cos_label = MathTex(r"\cos(\theta)", font_size=22, color=PRIMARY).move_to(axes.c2p(0.5, -0.4))
        sin_label = MathTex(r"i\sin(\theta)", font_size=22, color=ORANGE).move_to(axes.c2p(-0.5, 0.5))
        cos_label.set_opacity(0); sin_label.set_opacity(0)

        self.add(arc, p_dot)
        self.add_subcaption("As theta grows, the point rotates around the circle", duration=2)
        self.play(theta_tracker.animate.set_value(PI / 2), run_time=SLOW)
        self.play(FadeIn(cos_label), FadeIn(sin_label), run_time=FAST)
        self.wait(1.0)

        self.play(theta_tracker.animate.set_value(PI), run_time=SLOW)
        cos_label_target = MathTex(r"\cos(\pi) = -1", font_size=22, color=PRIMARY).move_to(axes.c2p(-0.6, -0.5))
        sin_label_target = MathTex(r"i\sin(\pi) = 0", font_size=22, color=ORANGE).move_to(axes.c2p(-0.6, 0.5))
        self.play(ReplacementTransform(cos_label, cos_label_target),
                  ReplacementTransform(sin_label, sin_label_target), run_time=NORMAL)
        self.wait(2.0)

        note = Text("At θ = π, the point lands at -1", font_size=22, color=ACCENT, font=MONO)
        note.to_edge(DOWN, buff=0.8)
        self.add_subcaption("At theta equals pi, the point lands at negative one", duration=3)
        self.play(Write(note), run_time=NORMAL)
        self.wait(3.0)
        self.play(FadeOut(Group(*self.mobjects)), run_time=0.5)


class Scene4_EulerBridge(Scene):
    def construct(self):
        self.camera.background_color = BG

        title = Text("The Bridge: Euler's Formula", font_size=36, color=WHITE, font=MONO, weight=BOLD)
        title.to_edge(UP, buff=0.6)
        self.add(title)

        question = MathTex(r"e^{i\theta} = \;", font_size=64, color=PRIMARY)
        question.to_edge(LEFT).shift(RIGHT * 2 + UP * 0.5)
        self.add_subcaption("What does it mean to raise e to an imaginary power?", duration=3)
        self.play(Write(question), run_time=SLOW)
        self.wait(1.5)

        answer = MathTex(r"e^{i\theta} = \cos\theta + i\sin\theta", font_size=56)
        answer.move_to(DOWN * 0.5)
        self.add_subcaption("The exponential function and rotation are the same thing", duration=3)
        self.play(Write(answer), run_time=SLOW)
        self.wait(2.5)

        note = Text(
            "The complex exponential IS rotation in the plane.",
            font_size=22,
            color=SECONDARY,
            font=MONO,
            opacity=0.85
        )
        note.to_edge(DOWN, buff=1.0)
        self.play(Write(note), run_time=NORMAL)
        self.wait(3.0)
        self.play(FadeOut(Group(*self.mobjects)), run_time=0.5)


class Scene5_TheReveal(Scene):
    def construct(self):
        self.camera.background_color = BG

        title = Text("The Reveal", font_size=36, color=WHITE, font=MONO, weight=BOLD)
        title.to_edge(UP, buff=0.6)
        self.add(title)

        step1 = MathTex(r"e^{i\theta} = \cos\theta + i\sin\theta", font_size=44, color=WHITE)
        step1.to_edge(UP).shift(DOWN * 1.0)
        self.play(Write(step1), run_time=SLOW)
        self.wait(2.0)

        step2 = MathTex(r"\text{Let } \theta = \pi", font_size=44, color=PURPLE)
        step2.next_to(step1, DOWN, buff=0.6)
        self.add_subcaption("Now substitute pi for theta", duration=2)
        self.play(Write(step2), run_time=NORMAL)
        self.wait(2.0)

        step3 = MathTex(r"e^{i\pi} = \cos\pi + i\sin\pi", font_size=44, color=WHITE)
        step3.next_to(step2, DOWN, buff=0.6)
        self.play(ReplacementTransform(step2.copy(), step3), run_time=NORMAL)
        self.wait(1.5)

        step4 = MathTex(r"e^{i\pi} = -1 + i\cdot 0", font_size=44)
        step4.next_to(step3, DOWN, buff=0.6)
        cos_pi = MathTex(r"-1", font_size=44).set_color(PRIMARY)
        sin_pi = MathTex(r"0", font_size=44).set_color(ORANGE)
        self.add_subcaption("Cosine of pi is negative one. Sine of pi is zero.", duration=3)
        self.play(ReplacementTransform(step3.copy(), step4), run_time=NORMAL)
        self.wait(2.0)

        step5 = MathTex(r"e^{i\pi} = -1", font_size=52, color=ACCENT)
        step5.next_to(step4, DOWN, buff=0.6)
        self.add_subcaption("e to the i pi equals negative one", duration=2)
        self.play(ReplacementTransform(step4.copy(), step5), run_time=SLOW)
        self.wait(2.0)

        final = MathTex(r"e^{i\pi} + 1 = 0", font_size=60)
        final.set_color_by_tex(r"e", RED_C)
        final.set_color_by_tex(r"i", ORANGE)
        final.set_color_by_tex(r"\pi", PURPLE)
        final.set_color_by_tex(r"1", PRIMARY)
        final.to_edge(DOWN, buff=1.2)

        brace = Brace(final, DOWN, color=WHITE, buff=0.4)
        brace_label = Text("Five fundamental constants. One identity.", font_size=20, color=WHITE, font=MONO, opacity=0.7)
        brace_label.next_to(brace, DOWN)

        self.add_subcaption("e to the i pi plus one equals zero. Five numbers. One equation.", duration=4)
        self.play(ReplacementTransform(step5.copy(), final), run_time=SLOW)
        self.wait(1.5)
        self.play(GrowFromCenter(brace), Write(brace_label), run_time=NORMAL)
        self.wait(4.0)
        self.play(FadeOut(Group(*self.mobjects)), run_time=0.5)


class Scene6_TheSilence(Scene):
    def construct(self):
        self.camera.background_color = BG

        final = MathTex(r"e^{i\pi} + 1 = 0", font_size=80)
        final.set_color_by_tex(r"e", RED_C)
        final.set_color_by_tex(r"i", ORANGE)
        final.set_color_by_tex(r"\pi", PURPLE)
        final.set_color_by_tex(r"1", PRIMARY)
        final.set_color_by_tex(r"0", WHITE)

        self.add_subcaption("e. i. pi. one. zero.", duration=4)
        self.play(FadeIn(final, run_time=SLOW * 1.5), run_time=SLOW * 1.5)
        self.wait(3.0)

        # Highlight each constant one by one
        for const, color in [(r"e", RED_C), (r"i", ORANGE), (r"\pi", PURPLE), (r"1", PRIMARY), (r"0", WHITE)]:
            hl = SurroundingRectangle(final, color=color, stroke_opacity=0.3, buff=0.2)
            self.play(Create(hl), run_time=0.3)
            self.wait(0.4)
            self.play(FadeOut(hl), run_time=0.3)

        self.wait(2.0)

        quote = Text(
            "\"The most remarkable formula in mathematics.\"",
            font_size=26,
            color=ACCENT,
            font=MONO,
            opacity=0.9
        )
        quote.to_edge(DOWN, buff=1.5)
        self.add_subcaption("The most remarkable formula in mathematics.", duration=3)
        self.play(Write(quote), run_time=SLOW)
        self.wait(4.0)
        self.play(FadeOut(Group(*self.mobjects)), run_time=0.5)
