import t, c
from stdint import *
import ast
import llvmlite
import memhub
import string
import stdio
import viperlib
import lib.core.Handles.HandlesTranslator as HT
import lib.core.Handles.HandlesExpr as HandlesExpr
import lib.core.Handles.HandlesExprCall as HandlesExprCall
import lib.core.Handles.HandlesFunctions as HandlesFunctions
import lib.core.Handles.HandlesClassDef as HandlesClassDef


# ============================================================
# HandlesBody - 语句分派（trans 单参模式，全方法调用）
#
# 所有语句类型通过 trans.XxxH.Handle(node) 分派到对应 Handle。
# 对应 TransPyC BodyHandle.HandleBodyLlvm 的 isinstance 分派。
# ============================================================


# ============================================================
# 语句翻译分派
# ============================================================
def translate_stmt(trans: HT.Translator | t.CPtr,
                   node: ast.AST | t.CPtr) -> int:
    """翻译单条语句，返回新增的变量数"""
    if node is None:
        return 0
    k: int = node.kind()

    if k == ast.ASTKind.Expr:
        return translate_expr_stmt(trans, node)
    elif k == ast.ASTKind.Assign:
        return trans.AssignH.Handle(node)
    elif k == ast.ASTKind.AnnAssign:
        return trans.AnnAssignH.Handle(node)
    elif k == ast.ASTKind.FunctionDef:
        # 嵌套函数定义：提升为顶层函数 + 创建闭包
        return HandlesFunctions.translate_nested_function_def(trans, node)
    elif k == ast.ASTKind.Return:
        return trans.ReturnH.Handle(node)
    elif k == ast.ASTKind.If:
        return trans.IfH.Handle(node)
    elif k == ast.ASTKind.While:
        return trans.WhileH.Handle(node)
    elif k == ast.ASTKind.AugAssign:
        return trans.AugAssignH.Handle(node)
    elif k == ast.ASTKind.For:
        return trans.ForH.Handle(node)
    elif k == ast.ASTKind.ClassDef:
        return HandlesClassDef.translate_class_def(trans, node)
    elif k == ast.ASTKind.Import:
        return trans.ImportsH.HandleImport(node)
    elif k == ast.ASTKind.ImportFrom:
        trans.ImportsH.HandleImportFromModule(node)
        return trans.ImportsH.HandleImportFromNames(node)
    elif k == ast.ASTKind.Global:
        return translate_global(trans, node)
    elif k == ast.ASTKind.Nonlocal:
        return translate_nonlocal(trans, node)
    elif k == ast.ASTKind.Pass:
        return 0
    elif k == ast.ASTKind.Break:
        return translate_break(trans)
    elif k == ast.ASTKind.Continue:
        return translate_continue(trans)
    return 0


# ============================================================
# 翻译 Global 语句: global x, y
#
# 将 names 中的变量名加入 _global_names 集合
# ============================================================
def translate_global(trans: HT.Translator | t.CPtr,
                     node: ast.AST | t.CPtr) -> int:
    """翻译 global 语句：记录 global 变量名"""
    gn: ast.Global | t.CPtr = (ast.Global | t.CPtr)(node)
    if gn is None:
        return 0
    names: list[ast.AST | t.CPtr] | t.CPtr = gn.names
    if names is None:
        return 0
    n: t.CSizeT = names.__len__()
    for i in range(n):
        nm_node: ast.AST | t.CPtr = names.get(i)
        if nm_node is not None and nm_node.kind() == ast.ASTKind.Name:
            nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(nm_node)
            if nm.id is not None:
                HT.add_global_name(trans, nm.id)
    return 0


# ============================================================
# 翻译 Nonlocal 语句: nonlocal x, y
#
# 将 names 中的变量名加入 _nonlocal_names 集合
# ============================================================
def translate_nonlocal(trans: HT.Translator | t.CPtr,
                       node: ast.AST | t.CPtr) -> int:
    """翻译 nonlocal 语句：记录 nonlocal 变量名"""
    nl: ast.Nonlocal | t.CPtr = (ast.Nonlocal | t.CPtr)(node)
    if nl is None:
        return 0
    names: list[ast.AST | t.CPtr] | t.CPtr = nl.names
    if names is None:
        return 0
    n: t.CSizeT = names.__len__()
    for i in range(n):
        nm_node: ast.AST | t.CPtr = names.get(i)
        if nm_node is not None and nm_node.kind() == ast.ASTKind.Name:
            nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(nm_node)
            if nm.id is not None:
                HT.add_nonlocal_name(trans, nm.id)
    return 0


# ============================================================
# 翻译表达式语句 Expr(value=Call(...))
# ============================================================
def translate_expr_stmt(trans: HT.Translator | t.CPtr,
                        node: ast.AST | t.CPtr) -> int:
    """翻译表达式语句（printf 调用等）"""
    ex: ast.Expr | t.CPtr = (ast.Expr | t.CPtr)(node)
    if ex is None:
        return 0
    call_node: ast.AST | t.CPtr = ex.value
    if call_node is None:
        return 0
    ck: int = call_node.kind()
    if ck != ast.ASTKind.Call:
        return 0

    cl: ast.Call | t.CPtr = (ast.Call | t.CPtr)(call_node)
    func_node: ast.AST | t.CPtr = cl.func
    if func_node is None:
        return 0

    func_name: str = HandlesExpr.get_func_name(func_node)
    if func_name is None:
        return 0

    # printf / print 走特殊路径（print 映射到 printf）
    if string.strcmp(func_name, "printf") == 0 or string.strcmp(func_name, "print") == 0:
        trans.ExprCallH.HandlePrintfCall(cl)
    else:
        # 通用函数调用（返回值丢弃）
        trans.ExprCallH.HandleCall(call_node)
    return 0


# ============================================================
# 预扫描：为局部变量提前创建 alloca
# ============================================================
def pre_scan_allocas(trans: HT.Translator | t.CPtr,
                     node: ast.AST | t.CPtr) -> int:
    """预扫描语句中的 AnnAssign，提前创建 alloca

    返回新增的变量数
    """
    if node is None:
        return 0
    return trans.AnnAssignH.PreScan(node)


# ============================================================
# 翻译 break 语句
# ============================================================
def translate_break(trans: HT.Translator | t.CPtr) -> int:
    """翻译 break 语句：跳转到循环 end 块"""
    builder: llvmlite.IRBuilder | t.CPtr = trans._cur_builder
    func: llvmlite.Function | t.CPtr = trans._cur_func
    pool: memhub.MemBuddy | t.CPtr = trans.Pool

    if builder is None or func is None:
        return 0

    # 发射 br 到 break 目标
    if trans._break_bb is not None:
        if llvmlite.builder_cur_block_is_terminated(builder) == 0:
            llvmlite.build_br(builder, trans._break_bb)

    # 创建死代码 BB，用于后续语句（break 后面的代码不可达）
    cnt: int = trans._label_counter
    trans._label_counter = cnt + 1
    name_buf: t.CChar | t.CPtr = pool.alloc(32)
    viperlib.snprintf(name_buf, 32, "dead.%d", cnt)
    dead_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf)
    llvmlite.position_at_end(builder, dead_bb)
    return 0


# ============================================================
# 翻译 continue 语句
# ============================================================
def translate_continue(trans: HT.Translator | t.CPtr) -> int:
    """翻译 continue 语句：跳转到循环 cond/incr 块"""
    builder: llvmlite.IRBuilder | t.CPtr = trans._cur_builder
    func: llvmlite.Function | t.CPtr = trans._cur_func
    pool: memhub.MemBuddy | t.CPtr = trans.Pool

    if builder is None or func is None:
        return 0

    # 发射 br 到 continue 目标
    if trans._continue_bb is not None:
        if llvmlite.builder_cur_block_is_terminated(builder) == 0:
            llvmlite.build_br(builder, trans._continue_bb)

    # 创建死代码 BB，用于后续语句
    cnt: int = trans._label_counter
    trans._label_counter = cnt + 1
    name_buf: t.CChar | t.CPtr = pool.alloc(32)
    viperlib.snprintf(name_buf, 32, "dead.%d", cnt)
    dead_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf)
    llvmlite.position_at_end(builder, dead_bb)
    return 0


# ============================================================
# 获取语句类型名（调试用）
# ============================================================
def get_stmt_kind_name(node: ast.AST | t.CPtr) -> str:
    """获取语句类型名"""
    if node is None:
        return None
    return node.type_name()
