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

namespace lsp::protocol
{
    // Document Highlight
    struct DocumentHighlightClientCapabilities
    {
        std::optional<boolean> dynamicRegistration;
    };

    struct DocumentHighlightOptions : WorkDoneProgressOptions
    {
    };

    struct DocumentHighlightRegistrationOptions : TextDocumentRegistrationOptions, DocumentHighlightOptions
    {
    };

    struct DocumentHighlightParams : TextDocumentPositionParams, WorkDoneProgressParams, PartialResultParams
    {
    };

    enum class DocumentHighlightKind
    {
        Text = 1,
        Read = 2,
        Write = 3
    };

    struct DocumentHighlight
    {
        Range range;
        DocumentHighlightKind kind;
    };

    // Document Link
    struct DocumentLinkClientCapabilities
    {
        std::optional<boolean> dynamicRegistration;
        std::optional<boolean> tooltipSupport;
    };

    struct DocumentLinkOptions : WorkDoneProgressOptions
    {
        boolean resolveProvider;
    };

    struct DocumentLinkRegistrationOptions : TextDocumentRegistrationOptions, DocumentLinkOptions
    {
    };

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

    struct DocumentLink
    {
        Range range;
        std::optional<URI> target;
        std::optional<string> tooltip;
        std::optional<LSPAny> data;
    };

    // Hover
    struct HoverClientCapabilities
    {
        std::optional<boolean> dynamicRegistration;
        std::optional<std::vector<MarkupKind>> contentFormat;
    };

    struct HoverOptions : WorkDoneProgressOptions
    {
    };

    struct HoverRegistrationOptions : TextDocumentRegistrationOptions, HoverOptions
    {
    };

    struct HoverParams : TextDocumentPositionParams, WorkDoneProgressParams
    {
    };

    struct Hover
    {
        MarkupContent contents;
        std::optional<Range> range;
    };

    // CodeLens
    struct ClientCodeLensResolveOptions
    {
        std::vector<string> properties;
    };

    struct CodeLensClientCapabilities
    {
        std::optional<boolean> dynamicRegistration;
        std::optional<ClientCodeLensResolveOptions> resolveSupport;
    };

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

    struct CodeLensRegistrationOptions : TextDocumentRegistrationOptions, CodeLensOptions
    {
    };

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

    struct CodeLens
    {
        Range range;
        std::optional<Command> command;
        std::optional<LSPAny> data;
    };

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

    // Fold Range
    using FoldingRangeKind = std::string_view;
    namespace FoldingRangeKindLiterals
    {
        inline constexpr FoldingRangeKind Comment = "comment";
        inline constexpr FoldingRangeKind Imports = "imports";
        inline constexpr FoldingRangeKind Region = "region";
    }

    struct FoldingRangeClientCapabilities
    {
        struct FoldingRangeKinds
        {
            std::vector<FoldingRangeKind> valueSet;
        };
        struct FoldingRange
        {
            std::optional<boolean> collapsedText;
        };

        std::optional<boolean> dynamicRegistration;
        std::optional<uinteger> rangeLimit;
        std::optional<boolean> lineFoldingOnly;
        std::optional<FoldingRangeKinds> foldingRangeKind;
        std::optional<FoldingRange> foldingRange;
    };

    struct FoldingRangeOptions : WorkDoneProgressOptions
    {
    };

    struct FoldingRangeRegistrationOptions : TextDocumentRegistrationOptions, FoldingRangeOptions, StaticRegistrationOptions
    {
    };

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

    struct FoldingRange
    {
        uinteger startLine;
        std::optional<uinteger> startCharacter;
        uinteger endLine;
        std::optional<uinteger> endCharacter;
        std::optional<FoldingRangeKind> kind;
        std::optional<string> collapsedText;
    };

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


    // Sekection Range
    struct SelectionRangeClientCapabilities
    {
        std::optional<boolean> dynamicRegistration;
    };

    struct SelectionRangeOptions : WorkDoneProgressOptions
    {
    };

    struct SelectionRangeRegistrationOptions : SelectionRangeOptions, TextDocumentRegistrationOptions, StaticRegistrationOptions
    {
    };

    struct SelectionRangeParams : WorkDoneProgressParams, PartialResultParams
    {
        TextDocumentIdentifier textDocument;
        std::vector<Position> positions;
    };

    struct SelectionRange
    {
        Range range;
        std::optional<SelectionRange*> selectionRange;
    };

    struct TextDocumentFilterClientCapabilities
    {
        std::optional<boolean> relativePatternSupport;
    };
}
