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

namespace lsp::protocol
{
    using SemanticTokenType = std::string_view;
    namespace SemanticTokenTypesLiterals
    {
        inline constexpr SemanticTokenType Namespace = "namespace";
        inline constexpr SemanticTokenType Type = "type";
        inline constexpr SemanticTokenType Class = "class";
        inline constexpr SemanticTokenType Enum = "enum";
        inline constexpr SemanticTokenType Interface = "interface";
        inline constexpr SemanticTokenType Struct = "struct";
        inline constexpr SemanticTokenType TypeParameter = "typeParameter";
        inline constexpr SemanticTokenType Parameter = "parameter";
        inline constexpr SemanticTokenType Variable = "variable";
        inline constexpr SemanticTokenType Property = "property";
        inline constexpr SemanticTokenType EnumMember = "enumMember";
        inline constexpr SemanticTokenType Event = "event";
        inline constexpr SemanticTokenType Function = "function";
        inline constexpr SemanticTokenType Method = "method";
        inline constexpr SemanticTokenType Macro = "macro";
        inline constexpr SemanticTokenType Keyword = "keyword";
        inline constexpr SemanticTokenType Modifier = "modifier";
        inline constexpr SemanticTokenType Comment = "comment";
        inline constexpr SemanticTokenType String = "string";
        inline constexpr SemanticTokenType Number = "number";
        inline constexpr SemanticTokenType Regexp = "regexp";
        inline constexpr SemanticTokenType Operator = "operator";
        inline constexpr SemanticTokenType Decorator = "decorator";
        inline constexpr SemanticTokenType Label = "label";
    }

    using SemanticTokenModifiers = std::string_view;
    namespace SemanticTokenModifiersLiterals
    {
        inline constexpr SemanticTokenModifiers Declaration = "declaration";
        inline constexpr SemanticTokenModifiers Definition = "definition";
        inline constexpr SemanticTokenModifiers Readonly = "readonly";
        inline constexpr SemanticTokenModifiers Static = "static";
        inline constexpr SemanticTokenModifiers Deprecated = "deprecated";
        inline constexpr SemanticTokenModifiers Abstract = "abstract";
        inline constexpr SemanticTokenModifiers Async = "async";
        inline constexpr SemanticTokenModifiers Modification = "modification";
        inline constexpr SemanticTokenModifiers Documentation = "documentation";
        inline constexpr SemanticTokenModifiers DefaultLibrary = "defaultLibrary";
    }

    using TokenFormat = std::string_view;
    namespace TokenFormatLiterals
    {
        inline constexpr TokenFormat Relative = "relative";
    }

    struct SemanticTokensLegend
    {
        std::vector<string> tokenTypes;
        std::vector<string> tokenModifiers;
    };

    struct SemanticTokensClientCapabilities
    {
        struct Requests
        {
            struct Full
            {
                std::optional<boolean> delta;
            };

            std::optional<boolean> range;
            std::variant<Full, boolean> full;
        };

        std::optional<boolean> dynamicRegistration;
        Requests requests;
        std::vector<TokenFormat> formats;
        std::vector<string> tokenTypes;
        std::vector<string> tokenModifiers;
        std::optional<boolean> overlappingTokenSupport;
        std::optional<boolean> multilineTokenSupport;
        std::optional<boolean> serverCancelSupport;
        std::optional<boolean> augmentsSyntaxTokens;
    };

    struct SemanticTokensOptions : WorkDoneProgressOptions
    {
        struct Full
        {
            std::optional<boolean> delta;
        };

        SemanticTokensLegend legend;
        std::optional<boolean> range;
        std::optional<std::variant<Full, boolean>> full;
    };

    struct SemanticTokensRegistrationOptions : TextDocumentRegistrationOptions, SemanticTokensOptions, StaticRegistrationOptions
    {
    };

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

    struct SemanticTokens
    {
        std::optional<string> resultId;
        std::vector<uinteger> data;
    };

    struct SemanticTokensPartialResult
    {
        std::vector<uinteger> data;
    };

    struct SemanticTokensDeltaParams : WorkDoneProgressParams, PartialResultParams
    {
        TextDocumentIdentifier textDocument;
        string previousResultId;
    };

    struct SemanticTokensEdit
    {
        uinteger start;
        uinteger deleteCount;
        std::optional<std::vector<uinteger>> data;
    };

    struct SemanticTokensDelta
    {
        std::optional<string> resultId;
        std::optional<std::vector<SemanticTokensEdit>> edits;
    };

    struct SemanticTokensDeltaPartialResult
    {
        std::optional<std::vector<SemanticTokensEdit>> edits;
    };

    struct SemanticTokensRangeParams : WorkDoneProgressParams, PartialResultParams
    {
        TextDocumentIdentifier textDocument;
        Range range;
    };

    struct SemanticTokensWorkspaceClientCapabilities
    {
        std::optional<boolean> refreshSupport;
    };
}
