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

namespace lsp::protocol
{
    using CodeActionKind = std::string_view;
    namespace CodeActionKindLiterals
    {
        inline constexpr CodeActionKind Empty = "";
        inline constexpr CodeActionKind QuickFix = "quickfix";
        inline constexpr CodeActionKind Refactor = "refactor";
        inline constexpr CodeActionKind RefactorExtract = "refactor.extract";
        inline constexpr CodeActionKind RefactorInline = "refactor.inline";
        inline constexpr CodeActionKind RefactorRewrite = "refactor.rewrite";
        inline constexpr CodeActionKind Source = "source";
        inline constexpr CodeActionKind SourceOrganizeImports = "source.organizeImports";
        inline constexpr CodeActionKind SourceFixAll = "source.fixAll";
    }

    enum class CodeActionTag
    {
        LLMGenerated = 1
    };

    struct CodeActionClientCapabilities
    {
        struct CodeActionLiteralSupport
        {
            struct CodeActionKinds
            {
                std::vector<CodeActionKind> valueSet;
            };
            CodeActionKinds codeActionKind;
        };

        struct ResolveSupport
        {
            std::vector<string> properties;
        };

        struct TagSupport
        {
            std::vector<CodeActionTag> valueSet;
        };

        std::optional<boolean> dynamicRegistration;
        std::optional<CodeActionLiteralSupport> codeActionLiteralSupport;
        std::optional<boolean> isPreferredSupport;
        std::optional<boolean> dataSupport;
        std::optional<boolean> disabledSupport;
        std::optional<ResolveSupport> resolveSupport;
        std::optional<boolean> honorsChangeAnnotations;
        std::optional<boolean> documentationSupport;
        std::optional<TagSupport> tagSupport;
    };

    struct CodeActionKindDocumentation
    {
        CodeActionKind kind;
        Command command;
    };

    struct CodeActionOptions : WorkDoneProgressOptions
    {
        std::optional<std::vector<CodeActionKind>> codeActionKinds;
        std::optional<std::vector<CodeActionKindDocumentation>> documentation;
        std::optional<boolean> resolveProvider;
    };

    struct CodeActionRegistrationOptions : TextDocumentRegistrationOptions, CodeActionOptions
    {
    };

    enum class CodeActionTriggerKind
    {
        kInvoked = 1,
        kAutomatic = 2
    };

    struct CodeActionContext
    {
        std::vector<Diagnostic> diagnostics;
        std::optional<std::vector<CodeActionKind>> only;
        std::optional<CodeActionTriggerKind> triggerKind;
    };

    struct CodeActionParams : TextDocumentPositionParams, WorkDoneProgressParams, PartialResultParams
    {
        TextDocumentIdentifier textDocument;
        Range range;
        CodeActionContext context;
    };

    struct CodeAction
    {
        struct Disabled
        {
            string reason;
        };

        string title;
        std::optional<CodeActionKind> kind;
        std::optional<std::vector<Diagnostic>> diagnostics;
        std::optional<boolean> isPreferred;
        std::optional<Disabled> disabled;
        std::optional<WorkspaceEdit> edit;
        std::optional<Command> command;
        std::optional<LSPAny> data;
        std::optional<CodeActionTag> tags;
    };

    // Color
    struct DocumentColorClientCapabilities
    {
        std::optional<boolean> dynamicRegistration;
    };

    struct DocumentColorOptions : WorkDoneProgressOptions
    {
    };

    struct DocumentColorRegistrationOptions : TextDocumentRegistrationOptions, DocumentColorOptions, StaticRegistrationOptions
    {
    };

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

    struct Color
    {
        decimal red;
        decimal green;
        decimal blue;
        decimal alpha;
    };

    struct ColorInformation
    {
        Range range;
        Color color;
    };

    struct ColorPresentationParams : WorkDoneProgressParams, PartialResultParams
    {
        TextDocumentIdentifier textDocument;
        Color color;
        Range range;
    };

    struct ColorPresentation
    {
        string label;
        std::optional<TextEdit> textEdit;
        std::optional<std::vector<TextEdit>> additionalTextEdits;
    };

}
