#pragma once
#include "./basic_types.hpp"
#include "./document_sync.hpp"
#include "./progress.hpp"
#include "./completion.hpp"

namespace lsp::protocol
{
    enum class SymbolKind
    {
        File = 1,
        Module = 2,
        Namespace = 3,
        Package = 4,
        Class = 5,
        Method = 6,
        Property = 7,
        Field = 8,
        Constructor = 9,
        Enum = 10,
        Interface = 11,
        Function = 12,
        Variable = 13,
        Constant = 14,
        String = 15,
        Number = 16,
        Boolean = 17,
        Array = 18,
        Object = 19,
        Key = 20,
        Null = 21,
        EnumMember = 22,
        Struct = 23,
        Event = 24,
        Operator = 25,
        TypeParameter = 26
    };

    enum class SymbolTag
    {
        Deprecated = 1
    };

    struct DocumentSymbol
    {
        string name;
        std::optional<string> detail;
        SymbolKind kind;
        std::optional<std::vector<SymbolTag>> tags;
        Range range;
        Range selectionRange;
        std::optional<std::vector<DocumentSymbol>> children;
    };

    struct SymbolInformation
    {
        string name;
        SymbolKind kind;
        std::optional<std::vector<SymbolTag>> tags;
        std::optional<boolean> deprecated;
        Location location;
        std::optional<string> containerName;
    };

    struct DocumentSymbolClientCapabilities
    {
        struct SymbolKinds
        {
            std::vector<SymbolKind> valueSet;
        };
        struct TagSupport
        {
            std::optional<std::vector<CompletionItemTag>> valueSet;
        };

        std::optional<boolean> dynamicRegistration;
        std::optional<SymbolKinds> symbolKind;
        std::optional<boolean> hierarchicalDocumentSymbolSupport;
        std::optional<TagSupport> tagSupport;
        std::optional<boolean> labelSupport;
    };

    struct DocumentSymbolOptions : WorkDoneProgressOptions
    {
        std::optional<string> label;
    };

    struct DocumentSymbolRegistrationOptions : TextDocumentRegistrationOptions, DocumentSymbolOptions
    {
    };

    struct DocumentSymbolParams : WorkDoneProgressParams, PartialResultParams
    {
        TextDocumentIdentifier textDocument;
    };

    struct WorkspaceSymbolClientCapabilities
    {
        struct SymbolKinds
        {
            std::vector<SymbolKind> valueSet;
        };
        struct TagSupport
        {
            std::optional<std::vector<CompletionItemTag>> valueSet;
        };
        struct ResolveSupport
        {
            std::vector<string> properties;
        };

        std::optional<boolean> dynamicRegistration;
        std::optional<SymbolKinds> symbolKind;
        std::optional<TagSupport> tagSupport;
        std::optional<ResolveSupport> resolveSupport;
    };

    struct WorkspaceSymbolOptions : WorkDoneProgressOptions
    {
        std::optional<boolean> resolveProvider;
    };

    struct WorkspaceSymbolRegistrationOptions : WorkspaceSymbolOptions
    {
    };

    struct WorkspaceSymbolParams : WorkDoneProgressParams, PartialResultParams
    {
        string query;
    };

    struct WorkspaceSymbol
    {
        struct LocationUriOnly
        {
            DocumentUri uri;
        };
        string name;
        SymbolKind kind;
        std::optional<std::vector<SymbolTag>> tags;
        std::optional<string> containerName;
        std::variant<Location, LocationUriOnly> location;
        std::optional<LSPAny> data;
    };

}
