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

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

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

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

    private:
        std::optional<protocol::Location> BuildDefinitionResponse(const protocol::DefinitionParams& params, ExecutionContext& context);
        std::optional<protocol::Location> FindLocalDefinition(const protocol::DocumentUri& uri, const protocol::Position& position, ExecutionContext& context);
        std::string GetIdentifierAtPosition(const protocol::DocumentUri& uri, const protocol::Position& position, ExecutionContext& context);

        TSNode FindDefinitionNode(TSNode root, const std::string& identifier, const std::string& content);
    };

    namespace
    {
        constexpr const char* kUnit = "unit";
        constexpr const char* kInterfaceSection = "interface_section";
        constexpr const char* kImplementationSection = "implementation_section";
        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* kIdentifier = "identifier";
        constexpr const char* kMethodWithImplementation = "method_with_implementation";
    }

}
