from manim import *
config.background_color = (33, 33, 33)


class FactorialTree(Scene):
    # This animation is fundamentally wrong, as it does NOT utilize this type of graph correctly
    # Still gets the job done though (I think)
    def construct(self):
        # Draw the initial node
        self.bottom = Text(f"factorial(5)", font_size=24, font="Agave Nerd Font Mono").to_edge(DOWN)
        self.play(Write(self.bottom))
        self.top_num = 1
        self.top = Text(f"result = 0", font_size=24, font="Agave Nerd Font Mono").to_edge(UP).to_edge(LEFT)
        self.last_node = None
        self.play(Write(self.top))
        root = self.create_node("5!", position=ORIGIN).to_edge(UP)
        self.play(FadeIn(root))
        
        def drawNode(node, parent, position, right = False):
            # Draw a multiplication sign in the center between the left and the right node
            
            self.bottom.become(Text(f"factorial({n})", font_size=24, font="Agave Nerd Font Mono").to_edge(DOWN))
            self.play(Indicate(self.bottom))

            self.play(GrowArrow(Arrow(parent.get_bottom(), node.get_top()).scale(0.5)))
            if final:
                self.play(Write(Text("x", font_size=24, font="Agave Nerd Font Mono").move_to(position + DOWN * 0.5)))
                self.last_node = node

            self.play(FadeIn(node))
            self.play(FadeToColor(node, GREEN))

        # Recursive function to create tree
        def factorialTree(n, parent, position, level=1):
            if n <= 0:
                # Closing animation
                self.play(FadeToColor(parent, GREEN))
                self.bottom.become(Text(f"factorial({n})", font_size=24, font="Agave Nerd Font Mono").to_edge(DOWN))
                self.play(Indicate(self.bottom))
                return

        
            # Left child (n-1)!
            left_pos = position + LEFT + level * DOWN
            left_child = self.create_node(f"{n-1}!", position=left_pos)
            
            drawNode(left_child, parent, position)
            factorial_tree(n-1, left_child, left_pos, level + 0.3)

            # Funky updates
            self.top_num *= n
            self.play(FadeToColor(parent, GREEN))

            # Right child (result of n-1 factorial)
            right_pos = position + RIGHT + level * DOWN
            right_child = self.create_node(str(self.top_num), position=right_pos)
            drawNode(right_child, parent, position, final=True, last=True)

            self.play(Transform(self.top, Text(f"result = {self.top_num}", font_size=24, font="Agave Nerd Font Mono").to_edge(UP).to_edge(LEFT)))
            
                
        # Create the tree
        factorial_tree(5, root, root.get_center())
        self.play(Indicate(self.last_node))
        self.wait(1)

    def create_node(self, content, position):
        node = Circle().scale(0.25)
        node_text = Text(content).scale(0.25).move_to(node)
        node_group = VGroup(node, node_text).move_to(position)
        return node_group
