"""
AST Nodes for the Prasad Programming Language
"""


class ASTNode:
    """Base class for all AST nodes."""

    pass


class Program(ASTNode):
    """Represents the entire program."""

    def __init__(self, statements):
        self.statements = statements

    def __repr__(self):
        return f"Program({self.statements})"


class NumberLiteral(ASTNode):
    """Represents a numeric literal."""

    def __init__(self, value):
        self.value = value

    def __repr__(self):
        return f"NumberLiteral({self.value})"


class StringLiteral(ASTNode):
    """Represents a string literal."""

    def __init__(self, value):
        self.value = value

    def __repr__(self):
        return f"StringLiteral({self.value})"


class Identifier(ASTNode):
    """Represents a variable name."""

    def __init__(self, name):
        self.name = name

    def __repr__(self):
        return f"Identifier({self.name})"


class BinaryExpression(ASTNode):
    """Represents binary operations like +, -, *, /, >, <."""

    def __init__(self, left, operator, right):
        self.left = left
        self.operator = operator
        self.right = right

    def __repr__(self):
        return f"BinaryExpression({self.left}, {self.operator}, {self.right})"


class VariableAssignment(ASTNode):
    """Represents variable assignment."""

    def __init__(self, identifier, value):
        self.identifier = identifier
        self.value = value

    def __repr__(self):
        return f"VariableAssignment({self.identifier}, {self.value})"


class FunctionDeclaration(ASTNode):
    """Represents function definition."""

    def __init__(self, name, params, body):
        self.name = name
        self.params = params
        self.body = body

    def __repr__(self):
        return f"FunctionDeclaration({self.name}, {self.params}, {self.body})"


class FunctionCall(ASTNode):
    """Represents calling a function."""

    def __init__(self, name, arguments):
        self.name = name
        self.arguments = arguments

    def __repr__(self):
        return f"FunctionCall({self.name}, {self.arguments})"


class IfStatement(ASTNode):
    """Represents 'jar / nahitar' conditional."""

    def __init__(self, condition, consequent, alternate=None):
        self.condition = condition
        self.consequent = consequent
        self.alternate = alternate

    def __repr__(self):
        return f"IfStatement({self.condition}, {self.consequent}, {self.alternate})"


class ForLoop(ASTNode):
    """Represents 'sathi' loop."""

    def __init__(self, initializer, condition, update, body):
        self.initializer = initializer
        self.condition = condition
        self.update = update
        self.body = body

    def __repr__(self):
        return (
            f"ForLoop({self.initializer}, {self.condition}, {self.update}, {self.body})"
        )


class BlockStatement(ASTNode):
    """Represents a block of statements inside { }."""

    def __init__(self, statements):
        self.statements = statements

    def __repr__(self):
        return f"BlockStatement({self.statements})"
