#include "sem/SymbolTable.h"
#include <antlr4-runtime.h>  // 用于访问父节点

// ---------- 构造函数 ----------
SymbolTable::SymbolTable() {
    scopes_.emplace_back(); // 初始化全局作用域
    registerBuiltinFunctions(); // 注册内置库函数
}

// ---------- 作用域管理 ----------
void SymbolTable::enterScope() {
    scopes_.emplace_back();
}

void SymbolTable::exitScope() {
    if (scopes_.size() > 1) {
        scopes_.pop_back();
    }
    // 不能退出全局作用域
}

// ---------- 符号添加与查找 ----------
bool SymbolTable::addSymbol(const Symbol& sym) {
    auto& current_scope = scopes_.back();
    if (current_scope.find(sym.name) != current_scope.end()) {
        return false;   // 重复定义
    }
    current_scope[sym.name] = sym;
    return true;
}

Symbol* SymbolTable::lookup(const std::string& name) {
    // 从当前作用域向外层查找
    for (auto it = scopes_.rbegin(); it != scopes_.rend(); ++it) {
        auto& scope = *it;
        auto found = scope.find(name);
        if (found != scope.end()) {
            return &found->second;
        }
    }
    return nullptr;
}

Symbol* SymbolTable::lookupCurrent(const std::string& name) {
    auto& current_scope = scopes_.back();
    auto it = current_scope.find(name);
    if (it != current_scope.end()) {
        return &it->second;
    }
    return nullptr;
}

// ---------- 兼容原接口 ----------
void SymbolTable::Add(const std::string& name, SysYParser::VarDefContext* decl) {
    Symbol sym;
    sym.name = name;
    sym.kind = SymbolKind::Variable;
    sym.type = getTypeFromVarDef(decl);
    sym.var_def_ctx = decl;
    sym.scope_level = currentScopeLevel();
    addSymbol(sym);
}

bool SymbolTable::Contains(const std::string& name) const {
    // const 方法不能修改 scopes_，我们模拟查找
    for (auto it = scopes_.rbegin(); it != scopes_.rend(); ++it) {
        if (it->find(name) != it->end()) {
            return true;
        }
    }
    return false;
}

SysYParser::VarDefContext* SymbolTable::Lookup(const std::string& name) const {
    for (auto it = scopes_.rbegin(); it != scopes_.rend(); ++it) {
        auto found = it->find(name);
        if (found != it->end()) {
            // 只返回变量定义的上下文（函数等其他符号返回 nullptr）
            if (found->second.kind == SymbolKind::Variable) {
                return found->second.var_def_ctx;
            }
            return nullptr;
        }
    }
    return nullptr;
}

// ---------- 辅助函数：从 VarDefContext 获取外层 VarDeclContext ----------
static SysYParser::VarDeclContext* getOuterVarDecl(SysYParser::VarDefContext* varDef) {
    auto parent = varDef->parent;
    while (parent) {
        if (auto varDecl = dynamic_cast<SysYParser::VarDeclContext*>(parent)) {
            return varDecl;
        }
        parent = parent->parent;
    }
    return nullptr;
}

// ---------- 辅助函数：从 VarDefContext 获取外层 ConstDeclContext（常量定义）----------
static SysYParser::ConstDeclContext* getOuterConstDecl(SysYParser::VarDefContext* varDef) {
    auto parent = varDef->parent;
    while (parent) {
        if (auto constDecl = dynamic_cast<SysYParser::ConstDeclContext*>(parent)) {
            return constDecl;
        }
        parent = parent->parent;
    }
    return nullptr;
}

// 常量表达式求值（占位，需实现真正的常量折叠）
static int evaluateConstExp(SysYParser::ConstExpContext* ctx) {
    // TODO: 实现常量折叠，目前返回0
    return 0;
}

// 从 VarDefContext 构造类型
std::shared_ptr<ir::Type> SymbolTable::getTypeFromVarDef(SysYParser::VarDefContext* ctx) {
    // 1. 获取基本类型（int/float）
    std::shared_ptr<ir::Type> base_type = nullptr;
    auto varDecl = getOuterVarDecl(ctx);
    if (varDecl) {
        auto bType = varDecl->bType();
        if (bType->Int()) {
            base_type = ir::Type::GetInt32Type();
        } else if (bType->Float()) {
            base_type = ir::Type::GetFloatType();
        }
    } else {
        auto constDecl = getOuterConstDecl(ctx);
        if (constDecl) {
            auto bType = constDecl->bType();
            if (bType->Int()) {
                base_type = ir::Type::GetInt32Type();
            } else if (bType->Float()) {
                base_type = ir::Type::GetFloatType();
            }
        }
    }

    if (!base_type) {
        base_type = ir::Type::GetInt32Type(); // 默认 int
    }

    // 2. 解析数组维度（从 varDef 的 constExp 列表获取）
    std::vector<int> dims;
    for (auto constExp : ctx->constExp()) {
        int dimVal = evaluateConstExp(constExp);
        dims.push_back(dimVal);
    }

    if (!dims.empty()) {
        return ir::Type::GetArrayType(base_type, dims);
    }
    return base_type;
}

// 从 FuncDefContext 构造函数类型
std::shared_ptr<ir::Type> SymbolTable::getTypeFromFuncDef(SysYParser::FuncDefContext* ctx) {
    // 1. 返回类型
    std::shared_ptr<ir::Type> ret_type;
    auto funcType = ctx->funcType();
    if (funcType->Void()) {
        ret_type = ir::Type::GetVoidType();
    } else if (funcType->Int()) {
        ret_type = ir::Type::GetInt32Type();
    } else if (funcType->Float()) {
        ret_type = ir::Type::GetFloatType();
    } else {
        ret_type = ir::Type::GetInt32Type(); // fallback
    }

    // 2. 参数类型
    std::vector<std::shared_ptr<ir::Type>> param_types;
    auto fParams = ctx->funcFParams();
    if (fParams) {
        for (auto param : fParams->funcFParam()) {
            std::shared_ptr<ir::Type> param_type;
            auto bType = param->bType();
            if (bType->Int()) {
                param_type = ir::Type::GetInt32Type();
            } else if (bType->Float()) {
                param_type = ir::Type::GetFloatType();
            } else {
                param_type = ir::Type::GetInt32Type();
            }

            // 处理数组参数：如果存在 [ ] 或 [ exp ]，退化为指针
            if (param->L_BRACK().size() > 0) {
                if (param_type->IsInt32()) {
                    param_type = ir::Type::GetPtrInt32Type();
                } else if (param_type->IsFloat()) {
                    param_type = ir::Type::GetPtrFloatType();
                }
            }
            param_types.push_back(param_type);
        }
    }

    return ir::Type::GetFunctionType(ret_type, param_types);
}

// ----- 注册内置库函数-----
void SymbolTable::registerBuiltinFunctions() {
    // 确保当前处于全局作用域（scopes_ 只有一层）
    // 1. getint: int getint()
    Symbol getint;
    getint.name = "getint";
    getint.kind = SymbolKind::Function;
    getint.type = ir::Type::GetFunctionType(ir::Type::GetInt32Type(), {});  // 无参数
    getint.param_types = {};
    getint.scope_level = 0;
    getint.is_builtin = true;
    addSymbol(getint);

    // 2. getfloat: float getfloat()
    Symbol getfloat;
    getfloat.name = "getfloat";
    getfloat.kind = SymbolKind::Function;
    getfloat.type = ir::Type::GetFunctionType(ir::Type::GetFloatType(), {});
    getfloat.param_types = {};
    getfloat.scope_level = 0;
    getfloat.is_builtin = true;
    addSymbol(getfloat);

    // 3. getch: int getch()
    Symbol getch;
    getch.name = "getch";
    getch.kind = SymbolKind::Function;
    getch.type = ir::Type::GetFunctionType(ir::Type::GetInt32Type(), {});
    getch.param_types = {};
    getch.scope_level = 0;
    getch.is_builtin = true;
    addSymbol(getch);

    // 4. putint: void putint(int)
    std::vector<std::shared_ptr<ir::Type>> putint_params = { ir::Type::GetInt32Type() };
    Symbol putint;
    putint.name = "putint";
    putint.kind = SymbolKind::Function;
    putint.type = ir::Type::GetFunctionType(ir::Type::GetVoidType(), putint_params);
    putint.param_types = putint_params;
    putint.scope_level = 0;
    putint.is_builtin = true;
    addSymbol(putint);

    // 5. putfloat: void putfloat(float)
    std::vector<std::shared_ptr<ir::Type>> putfloat_params = { ir::Type::GetFloatType() };
    Symbol putfloat;
    putfloat.name = "putfloat";
    putfloat.kind = SymbolKind::Function;
    putfloat.type = ir::Type::GetFunctionType(ir::Type::GetVoidType(), putfloat_params);
    putfloat.param_types = putfloat_params;
    putfloat.scope_level = 0;
    putfloat.is_builtin = true;
    addSymbol(putfloat);

    // 6. putch: void putch(int)
    std::vector<std::shared_ptr<ir::Type>> putch_params = { ir::Type::GetInt32Type() };
    Symbol putch;
    putch.name = "putch";
    putch.kind = SymbolKind::Function;
    putch.type = ir::Type::GetFunctionType(ir::Type::GetVoidType(), putch_params);
    putch.param_types = putch_params;
    putch.scope_level = 0;
    putch.is_builtin = true;
    addSymbol(putch);

    // 7. getarray: int getarray(int a[])
    // 参数类型: int a[] 退化为 int* 即 PtrInt32
    std::vector<std::shared_ptr<ir::Type>> getarray_params = { ir::Type::GetPtrInt32Type() };
    Symbol getarray;
    getarray.name = "getarray";
    getarray.kind = SymbolKind::Function;
    getarray.type = ir::Type::GetFunctionType(ir::Type::GetInt32Type(), getarray_params);
    getarray.param_types = getarray_params;
    getarray.scope_level = 0;
    getarray.is_builtin = true;
    addSymbol(getarray);

    // 8. putarray: void putarray(int n, int a[])
    // 参数: int n, int a[] -> 实际类型: int, int*
    std::vector<std::shared_ptr<ir::Type>> putarray_params = { ir::Type::GetInt32Type(), ir::Type::GetPtrInt32Type() };
    Symbol putarray;
    putarray.name = "putarray";
    putarray.kind = SymbolKind::Function;
    putarray.type = ir::Type::GetFunctionType(ir::Type::GetVoidType(), putarray_params);
    putarray.param_types = putarray_params;
    putarray.scope_level = 0;
    putarray.is_builtin = true;
    addSymbol(putarray);

    // starttime: void starttime()
    Symbol starttime;
    starttime.name = "starttime";
    starttime.kind = SymbolKind::Function;
    starttime.type = ir::Type::GetFunctionType(ir::Type::GetVoidType(), {});  // 无参数，返回 void
    starttime.param_types = {};
    starttime.scope_level = 0;
    starttime.is_builtin = true;
    addSymbol(starttime);

    // stoptime: void stoptime()
    Symbol stoptime;
    stoptime.name = "stoptime";
    stoptime.kind = SymbolKind::Function;
    stoptime.type = ir::Type::GetFunctionType(ir::Type::GetVoidType(), {});  // 无参数，返回 void
    stoptime.param_types = {};
    stoptime.scope_level = 0;
    stoptime.is_builtin = true;
    addSymbol(stoptime);

    // getfarray: int getfarray(float arr[])
    std::vector<std::shared_ptr<ir::Type>> getfarray_params = { ir::Type::GetPtrFloatType() };
    Symbol getfarray;
    getfarray.name = "getfarray";
    getfarray.kind = SymbolKind::Function;
    getfarray.type = ir::Type::GetFunctionType(ir::Type::GetInt32Type(), getfarray_params);
    getfarray.param_types = getfarray_params;
    getfarray.scope_level = 0;
    getfarray.is_builtin = true;
    addSymbol(getfarray);

    // putfarray: void putfarray(int len, float arr[])
    std::vector<std::shared_ptr<ir::Type>> putfarray_params = { 
        ir::Type::GetInt32Type(), 
        ir::Type::GetPtrFloatType() 
    };
    Symbol putfarray;
    putfarray.name = "putfarray";
    putfarray.kind = SymbolKind::Function;
    putfarray.type = ir::Type::GetFunctionType(ir::Type::GetVoidType(), putfarray_params);
    putfarray.param_types = putfarray_params;
    putfarray.scope_level = 0;
    putfarray.is_builtin = true;
    addSymbol(putfarray);
}