#pragma once

#include "./table.hpp"

namespace lsp::language::symbol
{
    // 符号表构建器
    class Builder : public ast::ASTVisitor
    {
    public:
        explicit Builder(SymbolTable& table);

        void Build(ast::ASTNode& root);

        // 访问语句和声明
        void VisitProgram(ast::Program& node) override;
        void VisitUnitDefinition(ast::UnitDefinition& node) override;
        void VisitClassDefinition(ast::ClassDefinition& node) override;
        void VisitFunctionDefinition(ast::FunctionDefinition& node) override;
        void VisitFunctionDeclaration(ast::FunctionDeclaration& node) override;
        void VisitMethodDeclaration(ast::MethodDeclaration& node) override;
        void VisitPropertyDeclaration(ast::PropertyDeclaration& node) override;
        void VisitExternalMethodDefinition(ast::ExternalMethodDefinition& node) override;
        void VisitClassMember(ast::ClassMember& node) override;
        void VisitVarStatement(ast::VarStatement& node) override;
        void VisitStaticStatement(ast::StaticStatement& node) override;
        void VisitGlobalStatement(ast::GlobalStatement& node) override;
        void VisitConstStatement(ast::ConstStatement& node) override;
        void VisitVarDeclaration(ast::VarDeclaration& node) override;
        void VisitStaticDeclaration(ast::StaticDeclaration& node) override;
        void VisitGlobalDeclaration(ast::GlobalDeclaration& node) override;
        void VisitFieldDeclaration(ast::FieldDeclaration& node) override;
        void VisitBlockStatement(ast::BlockStatement& node) override;
        void VisitIfStatement(ast::IfStatement& node) override;
        void VisitForInStatement(ast::ForInStatement& node) override;
        void VisitForToStatement(ast::ForToStatement& node) override;
        void VisitWhileStatement(ast::WhileStatement& node) override;
        void VisitRepeatStatement(ast::RepeatStatement& node) override;
        void VisitCaseStatement(ast::CaseStatement& node) override;
        void VisitTryStatement(ast::TryStatement& node) override;

        // Uses 语句处理
        void VisitUsesStatement(ast::UsesStatement& node) override;

        // 访问表达式(收集引用)
        void VisitIdentifier(ast::Identifier& node) override;
        void VisitCallExpression(ast::CallExpression& node) override;
        void VisitAttributeExpression(ast::AttributeExpression& node) override;
        void VisitAssignmentExpression(ast::AssignmentExpression& node) override;
        void VisitAssignmentStatement(ast::AssignmentStatement& node) override;

        // 其他节点访问
        void VisitLiteral(ast::Literal&) override {}
        void VisitBinaryExpression(ast::BinaryExpression& node) override;
        void VisitUnaryExpression(ast::UnaryExpression& node) override;
        void VisitTernaryExpression(ast::TernaryExpression& node) override;
        void VisitSubscriptExpression(ast::SubscriptExpression& node) override;
        void VisitArrayExpression(ast::ArrayExpression& node) override;
        void VisitAnonymousFunctionExpression(ast::AnonymousFunctionExpression& node) override;
        void VisitPrefixIncrementExpression(ast::PrefixIncrementExpression& node) override;
        void VisitPrefixDecrementExpression(ast::PrefixDecrementExpression& node) override;
        void VisitPostfixIncrementExpression(ast::PostfixIncrementExpression& node) override;
        void VisitPostfixDecrementExpression(ast::PostfixDecrementExpression& node) override;
        void VisitFunctionPointerExpression(ast::FunctionPointerExpression&) override {}
        void VisitComparisonExpression(ast::ComparisonExpression& node) override;
        void VisitExpressionStatement(ast::ExpressionStatement& node) override;
        void VisitBreakStatement(ast::BreakStatement&) override {}
        void VisitContinueStatement(ast::ContinueStatement&) override {}
        void VisitReturnStatement(ast::ReturnStatement& node) override;
        void VisitTSSQLExpression(ast::TSSQLExpression&) override {}
        void VisitUnpackPattern(ast::UnpackPattern&) override {}
        void VisitMatrixIterationStatement(ast::MatrixIterationStatement& node) override;
        void VisitCompilerDirectiveStatement(ast::CompilerDirectiveStatement& node) override;
        void VisitConditionalDirectiveStatement(ast::ConditionalDirectiveStatement& node) override;
        void VisitConditionalBlockStatement(ast::ConditionalBlockStatement& node) override;

    private:
        SymbolId CreateSymbol(const std::string& name, SymbolKind kind, const ast::ASTNode& node, const std::optional<std::string>& type_hint = std::nullopt, bool is_class_method = false);
        ScopeId EnterScopeWithSymbol(ScopeKind kind, SymbolId symbol_id, const ast::Location& range);
        ScopeId EnterScope(ScopeKind kind, const ast::Location& range);

        void ExitScope();
        void VisitStatements(const std::vector<ast::StatementPtr>& statements);
        void VisitExpression(ast::Expression& expr);
        void ProcessLeftHandSide(const ast::LeftHandSide& lhs, bool is_write);
        std::string FormatSignature(const ast::Signature& signature);

    private:
        SymbolTable& table_;
        ScopeId current_scope_id_;
        std::optional<SymbolId> current_parent_symbol_id_;
        std::optional<SymbolId> current_function_id_;
    };

}
