#include "../../include/sem/SymbolTable.h"
#include <stdexcept>
#include <string>
#include <iostream>

// 进入新作用域
void SymbolTable::EnterScope() {
    scopes_.push(ScopeEntry());
}

// 离开当前作用域
void SymbolTable::LeaveScope() {
    if (scopes_.empty()) {
        throw std::runtime_error("SymbolTable Error: 作用域栈为空，无法退出");
    }
    scopes_.pop();
}

// 绑定变量到当前作用域
void SymbolTable::BindVar(const std::string& name, const VarInfo& info, void* decl_ctx) {
    if (CurrentScopeHasVar(name)) {
        throw std::runtime_error("变量'" + name + "'在当前作用域重复定义");
    }
    scopes_.top().var_symbols[name] = {info, decl_ctx};
}

// 绑定函数到当前作用域
void SymbolTable::BindFunc(const std::string& name, const FuncInfo& info, void* decl_ctx) {
    if (CurrentScopeHasFunc(name)) {
        throw std::runtime_error("函数'" + name + "'在当前作用域重复定义");
    }
    scopes_.top().func_symbols[name] = {info, decl_ctx};
}

// 查找变量（从当前作用域向上遍历）
bool SymbolTable::LookupVar(const std::string& name, VarInfo& out_info, void*& out_decl_ctx) const {
    if (scopes_.empty()) {
        return false;
    }
    auto temp_stack = scopes_;
    while (!temp_stack.empty()) {
        auto& scope = temp_stack.top();
        auto it = scope.var_symbols.find(name);
        if (it != scope.var_symbols.end()) {
            out_info = it->second.first;
            out_decl_ctx = it->second.second;
            return true;
        }
        temp_stack.pop();
    }
    return false;
}

// 查找函数（从当前作用域向上遍历，通常函数在全局作用域）
bool SymbolTable::LookupFunc(const std::string& name, FuncInfo& out_info, void*& out_decl_ctx) const {
    if (scopes_.empty()) {
        return false;
    }
    auto temp_stack = scopes_;
    while (!temp_stack.empty()) {
        auto& scope = temp_stack.top();
        auto it = scope.func_symbols.find(name);
        if (it != scope.func_symbols.end()) {
            out_info = it->second.first;
            out_decl_ctx = it->second.second;
            return true;
        }
        temp_stack.pop();
    }
    return false;
}

// 检查当前作用域是否包含指定变量
bool SymbolTable::CurrentScopeHasVar(const std::string& name) const {
    if (scopes_.empty()) {
        return false;
    }
    return scopes_.top().var_symbols.count(name) > 0;
}

// 检查当前作用域是否包含指定函数
bool SymbolTable::CurrentScopeHasFunc(const std::string& name) const {
    if (scopes_.empty()) {
        return false;
    }
    return scopes_.top().func_symbols.count(name) > 0;
}

// 进入循环
void SymbolTable::EnterLoop() { 
    loop_depth_++; 
}

// 离开循环
void SymbolTable::ExitLoop() { 
    if (loop_depth_ > 0) loop_depth_--;
}

// 检查是否在循环内
bool SymbolTable::InLoop() const { 
    return loop_depth_ > 0; 
}

// 清空所有作用域和状态
void SymbolTable::Clear() {
    while (!scopes_.empty()) {
        scopes_.pop();
    }
    loop_depth_ = 0;
}

// 获取当前作用域中所有变量名
std::vector<std::string> SymbolTable::GetCurrentScopeVarNames() const {
    std::vector<std::string> names;
    if (!scopes_.empty()) {
        for (const auto& pair : scopes_.top().var_symbols) {
            names.push_back(pair.first);
        }
    }
    return names;
}

// 获取当前作用域中所有函数名
std::vector<std::string> SymbolTable::GetCurrentScopeFuncNames() const {
    std::vector<std::string> names;
    if (!scopes_.empty()) {
        for (const auto& pair : scopes_.top().func_symbols) {
            names.push_back(pair.first);
        }
    }
    return names;
}

// 调试：打印符号表内容
void SymbolTable::Dump() const {
    std::cout << "符号表内容 (作用域深度: " << scopes_.size() << "):\n";
    int scope_idx = 0;
    auto temp_stack = scopes_;
    
    while (!temp_stack.empty()) {
        std::cout << "\n作用域 " << scope_idx++ << ":\n";
        auto& scope = temp_stack.top();
        
        std::cout << "  变量:\n";
        for (const auto& var_pair : scope.var_symbols) {
            const VarInfo& info = var_pair.second.first;
            std::cout << "    " << var_pair.first << ": "
                      << SymbolTypeToString(info.type)
                      << (info.is_const ? " (const)" : "")
                      << (info.IsArray() ? " [数组]" : "")
                      << "\n";
        }
        
        std::cout << "  函数:\n";
        for (const auto& func_pair : scope.func_symbols) {
            const FuncInfo& info = func_pair.second.first;
            std::cout << "    " << func_pair.first << ": "
                      << SymbolTypeToString(info.ret_type) << " ("
                      << info.param_types.size() << " 个参数)\n";
        }
        
        temp_stack.pop();
    }
}