#pragma once

#include <unordered_map>
#include <vector>
#include "./types.hpp"

namespace lsp::language::symbol
{
    // 引用图
    class ReferenceGraph
    {
    public:
        void AddReference(SymbolId symbol_id, const ast::Location& location, bool is_definition = false, bool is_write = false);
        void Clear();

        // 返回引用避免拷贝，如果不存在返回 nullptr
        const std::vector<Reference>* GetReferences(SymbolId symbol_id) const;
        std::optional<ast::Location> GetDefinition(SymbolId symbol_id) const;

    private:
        std::unordered_map<SymbolId, std::vector<Reference>> references_;
    };

    // 继承图
    class InheritanceGraph
    {
    public:
        void AddInheritance(SymbolId derived_class, SymbolId base_class);
        void Clear();

        // 返回引用避免拷贝
        const std::vector<SymbolId>* GetBaseClasses(SymbolId class_id) const;
        const std::vector<SymbolId>* GetDerivedClasses(SymbolId class_id) const;
        bool IsSubclassOf(SymbolId derived, SymbolId base) const;

    private:
        std::unordered_map<SymbolId, std::vector<SymbolId>> base_classes_;
        std::unordered_map<SymbolId, std::vector<SymbolId>> derived_classes_;
    };

    // 调用图
    class CallGraph
    {
    public:
        void AddCall(SymbolId caller, SymbolId callee, const ast::Location& location);
        void Clear();

        // 返回引用避免拷贝
        const std::vector<CallRelation>* GetCallers(SymbolId function_id) const;
        const std::vector<CallRelation>* GetCallees(SymbolId function_id) const;

    private:
        std::unordered_map<SymbolId, std::vector<CallRelation>> callers_;
        std::unordered_map<SymbolId, std::vector<CallRelation>> callees_;
    };

}
