#pragma once
#include "../base/interface.hpp"

extern "C" {
#include <tree_sitter/api.h>
}

namespace lsp::provider::text_document
{
    class References : public IRequestProvider
    {
    public:
        References() = default;

        std::string GetMethod() const override;
        std::string GetProviderName() const override;
        std::string ProvideResponse(const protocol::RequestMessage& request, ExecutionContext& context) override;

    private:
        std::vector<protocol::Location> BuildReferencesResponse(const protocol::ReferenceParams& params, ExecutionContext& context);
        std::vector<protocol::Location> FindReferences(const protocol::DocumentUri& uri, const std::string& identifier, bool include_declaration, ExecutionContext& context);
        std::string GetIdentifierAtPosition(const protocol::DocumentUri& uri, const protocol::Position& position, ExecutionContext& context);
        void FindReferencesInNode(TSNode node, const std::string& identifier, const std::string& content, const protocol::DocumentUri& uri, std::vector<protocol::Location>& locations, bool include_declaration);
        bool IsDefinitionNode(TSNode node, const std::string& identifier, const std::string& content);
        bool IsReferenceNode(TSNode node, const std::string& identifier, const std::string& content);
    };

    namespace
    {
        constexpr const char* kIdentifier = "identifier";
        constexpr const char* kCall = "call";
        constexpr const char* kAttribute = "attribute";
        constexpr const char* kFunctionDefinition = "function_definition_statement";
        constexpr const char* kFunctionDeclaration = "function_declaration_statement";
        constexpr const char* kClassDefinition = "class_definition_statement";
        constexpr const char* kVarStatement = "var_statement";
        constexpr const char* kConstStatement = "const_statement";
        constexpr const char* kMethodWithImplementation = "method_with_implementation";
        constexpr const char* kAssignmentExpression = "assignment_expression";
    }

}
