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

namespace lsp::protocol
{
    // Inlay Hints
    struct InlayHintClientCapabilities
    {
        struct ResolveSupport
        {
            std::vector<string> properties;
        };
        std::optional<boolean> dynamicRegistration;
        std::optional<ResolveSupport> resolveSupport;
    };

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

    struct InlayHintRegistrationOptions : TextDocumentRegistrationOptions, InlayHintOptions, StaticRegistrationOptions
    {
    };

    struct InlayHintParams : WorkDoneProgressParams
    {
        TextDocumentIdentifier textDocument;
        Range range;
    };

    struct InlayHintLabelPart
    {
        string value;
        std::optional<std::variant<string, MarkupContent>> tooltip;
        std::optional<Location> location;
        std::optional<Command> command;
    };

    enum class InlayHintKind
    {
        Type = 1,
        Parameter = 2
    };

    struct InlayHint
    {
        Position position;
        std::variant<string, std::vector<InlayHintLabelPart>> label;
        std::optional<InlayHintKind> kind;
        std::optional<std::vector<TextEdit>> textEdits;
        ;
        std::optional<std::variant<string, MarkupContent>> tooltip;
        std::optional<boolean> paddingLeft;
        std::optional<boolean> paddingRight;
        std::optional<LSPAny> data;
    };

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

    // Inline Values
    struct InlineValueClientCapabilities
    {
        std::optional<boolean> dynamicRegistration;
    };

    struct InlineValueOptions : WorkDoneProgressOptions
    {
    };

    struct InlineValueRegistrationOptions : TextDocumentRegistrationOptions, InlineValueOptions, StaticRegistrationOptions
    {
    };

    struct InlineValueContent
    {
        integer frameId;
        Range stoppedLocation;
    };

    struct InlineValueText
    {
        Range range;
        string text;
    };

    struct InlineValueParams : WorkDoneProgressParams
    {
        TextDocumentIdentifier textDocument;
        Range range;
        InlineValueContent context;
    };

    struct InlineValueVariableLookup
    {
        Range range;
        std::optional<string> variableName;
        std::optional<boolean> caseSensitiveLookup;
    };

    struct InlineValueEvaluatableExpression
    {
        Range range;
        std::optional<string> expression;
    };
    using InlineValue = std::variant<InlineValueText, InlineValueVariableLookup, InlineValueEvaluatableExpression>;

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

    // Moniker
    struct MonikerClientCapabilities
    {
        std::optional<boolean> dynamicRegistration;
    };

    struct MonikerOptions : WorkDoneProgressOptions
    {
    };

    struct MonikerRegistrationOptions : TextDocumentRegistrationOptions, MonikerOptions
    {
    };

    struct MonikerParams : TextDocumentPositionParams, WorkDoneProgressParams, PartialResultParams
    {
    };

    using UniquenessLevel = std::string_view;
    namespace UniquenessLevelLiterals
    {
        inline constexpr UniquenessLevel Document = "document";
        inline constexpr UniquenessLevel Project = "project";
        inline constexpr UniquenessLevel Group = "group";
        inline constexpr UniquenessLevel Scheme = "scheme";
        inline constexpr UniquenessLevel Global = "global";
    }

    using MonikerKind = std::string_view;
    namespace MonikerKindLiterals
    {
        inline constexpr MonikerKind Import = "import";
        inline constexpr MonikerKind Export = "export";
        inline constexpr MonikerKind Local = "local";
    }

    struct Moniker
    {
        string scheme;
        string identifier;
        UniquenessLevel unique;
        std::optional<MonikerKind> kind;
    };

}
