#pragma once
#include "./basic_types.hpp"
#include "./progress.hpp"
#include "./diagnostics.hpp"
#include "./workspace.hpp"
#include "./document_sync.hpp"
#include "./completion.hpp"
#include "./document_features.hpp"
#include "./symbols.hpp"
#include "./navigation.hpp"
#include "./code_actions.hpp"
#include "./formatting.hpp"
#include "./rename.hpp"
#include "./semantic_tokens.hpp"
#include "./inline_features.hpp"
#include "./signature_help.hpp"
#include "./notebook.hpp"
#include "./file_operations.hpp"
#include "./configuration.hpp"

namespace lsp::protocol
{
    struct TextDocumentClientCapabilities
    {
        std::optional<TextDocumentSyncClientCapabilities> synchronization;
        std::optional<TextDocumentFilterClientCapabilities> filters;
        std::optional<CompletionClientCapabilities> completion;
        std::optional<HoverClientCapabilities> hover;
        std::optional<SignatureHelpClientCapabilities> signatureHelp;
        std::optional<DeclarationClientCapabilities> declaration;
        std::optional<DefinitionClientCapabilities> definition;
        std::optional<ReferenceClientCapabilities> references;
        std::optional<TypeDefinitionClientCapabilities> typeDefinition;
        std::optional<ImplementationClientCapabilities> implementation;
        std::optional<ReferenceClientCapabilities> reference;
        std::optional<DocumentHighlightClientCapabilities> documentHighlight;
        std::optional<DocumentSymbolClientCapabilities> documentSymbol;
        std::optional<CodeActionClientCapabilities> codeAction;
        std::optional<CodeLensClientCapabilities> codeLens;
        std::optional<DocumentLinkClientCapabilities> documentLink;
        std::optional<DocumentColorClientCapabilities> colorProvider;
        std::optional<DocumentFormattingClientCapabilities> formatting;
        std::optional<DocumentRangeFormattingClientCapabilities> rangeFormatting;
        std::optional<DocumentOnTypeFormattingClientCapabilities> onTypeFormatting;
        std::optional<RenameClientCapabilities> rename;
        std::optional<PublishDiagnosticsClientCapabilities> publishDiagnostics;
        std::optional<FoldingRangeClientCapabilities> foldingRange;
        std::optional<SelectionRangeClientCapabilities> selectionRange;
        std::optional<LinkedEditingRangeClientCapabilities> linkedEditingRange;
        std::optional<CallHierarchyClientCapabilities> callHierarchy;
        std::optional<SemanticTokensClientCapabilities> semanticTokens;
        std::optional<MonikerClientCapabilities> moniker;
        std::optional<TypeHierarchyClientCapabilities> typeHierarchy;
        std::optional<InlineValueClientCapabilities> inlineValue;
        std::optional<InlayHintClientCapabilities> inlayHint;
        std::optional<DiagnosticClientCapabilities> diagnostic;
        std::optional<InlineCompletionClientCapabilities> inlineCompletion;
    };

    struct ClientCapabilities
    {
        struct Workspace
        {
            struct FileOperations
            {
                std::optional<boolean> dynamicRegistration;
                std::optional<boolean> didCreate;
                std::optional<boolean> willCreate;
                std::optional<boolean> didRename;
                std::optional<boolean> willRename;
                std::optional<boolean> didDelete;
                std::optional<boolean> willDelete;
            };

            std::optional<boolean> applyEdit;
            std::optional<WorkspaceEditClientCapabilities> workspaceEdit;
            std::optional<DidChangeConfigurationClientCapabilities> didChangeConfiguration;
            std::optional<DidChangeWatchedFilesClientCapabilities> didChangeWatchedFiles;
            std::optional<WorkspaceSymbolClientCapabilities> symbol;
            std::optional<ExecuteCommandClientCapabilities> executeCommand;
            std::optional<boolean> workspaceFolders;
            std::optional<boolean> configuration;
            std::optional<FoldingRangeWorkspaceClientCapabilities> foldingRange;
            std::optional<SemanticTokensWorkspaceClientCapabilities> semanticTokens;
            std::optional<CodeLensWorkspaceClientCapabilities> codeLens;
            std::optional<FileOperations> fileOperations;
            std::optional<InlineValueWorkspaceClientCapabilities> inlineValue;
            std::optional<InlayHintWorkspaceClientCapabilities> inlayHint;
            std::optional<DiagnosticWorkspaceClientCapabilities> diagnostics;
            std::optional<TextDocumentContentClientCapabilities> textDocumentContent;
        };
        struct Window
        {
            std::optional<boolean> workDoneProgress;
            std::optional<ShowMessageRequestClientCapabilities> showMessage;
            std::optional<ShowDocumentClientCapabilities> showDocument;
        };
        struct General
        {
            struct StaleRequestSupport
            {
                boolean cancel;
                std::vector<string> retryOnContentModified;
            };

            std::optional<StaleRequestSupport> staleRequestSupport;
            std::optional<RegularExpressionsClientCapabilities> regularExpressions;
            std::optional<MarkdownClientCapabilities> markdown;
            std::optional<std::vector<PositionEncodingKind>> positionEncodings;
        };

        std::optional<Workspace> workspace;
        std::optional<TextDocumentClientCapabilities> textDocument;
        std::optional<NotebookDocumentClientCapabilities> notebookDocument;
        std::optional<Window> window;
        std::optional<General> general;
        std::optional<LSPAny> experimental;
    };

    struct ServerCapabilities
    {
        struct Workspace
        {
            struct FileOperations
            {
                std::optional<boolean> dynamicRegistration;
                std::optional<boolean> didCreate;
                std::optional<boolean> willCreate;
                std::optional<boolean> didRename;
                std::optional<boolean> willRename;
                std::optional<boolean> didDelete;
                std::optional<boolean> willDelete;
            };

            std::optional<WorkspaceFolderServerCapabilities> workspaceFolders;
            std::optional<FileOperations> fileOperations;
        };

        struct TextDocument
        {
            struct Diagnostic
            {
                std::optional<boolean> markupMessageSupport;
            };
            std::optional<Diagnostic> diagnostic;
        };

        std::optional<PositionEncodingKind> positionEncoding;
        std::optional<std::variant<TextDocumentSyncOptions, TextDocumentSyncKind>> textDocumentSync;
        std::optional<std::variant<NotebookDocumentSyncOptions, NotebookDocumentSyncRegistrationOptions>> notebookDocumentSync;
        std::optional<CompletionOptions> completionProvider;
        std::optional<std::variant<boolean, HoverOptions>> hoverProvider;
        std::optional<SignatureHelpOptions> signatureHelpProvider;
        std::optional<std::variant<boolean, DeclarationOptions, DeclarationRegistrationOptions>> declarationProvider;
        std::optional<std::variant<boolean, DefinitionOptions>> definitionProvider;
        std::optional<std::variant<boolean, TypeDefinitionOptions, TypeDefinitionRegistrationOptions>> typeDefinitionProvider;
        std::optional<std::variant<boolean, ImplementationOptions, ImplementationRegistrationOptions>> implementationProvider;
        std::optional<std::variant<boolean, ReferenceOptions>> referencesProvider;
        std::optional<std::variant<boolean, DocumentHighlightOptions>> documentHighlightProvider;
        std::optional<std::variant<boolean, DocumentSymbolOptions>> documentSymbolProvider;
        std::optional<std::variant<boolean, CodeActionOptions>> codeActionProvider;
        std::optional<CodeLensOptions> codeLensProvider;
        std::optional<DocumentLinkOptions> documentLinkProvider;
        std::optional<std::variant<boolean, DocumentColorOptions, DocumentColorRegistrationOptions>> colorProvider;
        std::optional<std::variant<boolean, DocumentFormattingOptions>> documentFormattingProvider;
        std::optional<std::variant<boolean, DocumentRangeFormattingOptions>> documentRangeFormattingProvider;
        std::optional<DocumentOnTypeFormattingOptions> documentOnTypeFormattingProvider;
        std::optional<std::variant<boolean, RenameOptions>> renameProvider;
        std::optional<std::variant<boolean, FoldingRangeOptions, FoldingRangeRegistrationOptions>> foldingRangeProvider;
        std::optional<ExecuteCommandOptions> executeCommandProvider;
        std::optional<std::variant<boolean, SelectionRangeOptions, SelectionRangeRegistrationOptions>> selectionRangeProvider;
        std::optional<std::variant<boolean, LinkedEditingRangeOptions, LinkedEditingRangeRegistrationOptions>> linkedEditingRangeProvider;
        std::optional<std::variant<boolean, CallHierarchyOptions, CallHierarchyRegistrationOptions>> callHierarchyProvider;
        std::optional<std::variant<SemanticTokensOptions, SemanticTokensRegistrationOptions>> semanticTokensProvider;
        std::optional<std::variant<boolean, MonikerOptions, MonikerRegistrationOptions>> monikerProvider;
        std::optional<std::variant<boolean, TypeHierarchyOptions, TypeHierarchyRegistrationOptions>> typeHierarchyProvider;
        std::optional<std::variant<boolean, InlineValueOptions, InlineValueRegistrationOptions>> inlineValueProvider;
        std::optional<std::variant<boolean, InlayHintOptions, InlayHintRegistrationOptions>> inlayHintProvider;
        std::optional<std::variant<DiagnosticOptions, DiagnosticRegistrationOptions>> diagnosticProvider;
        std::optional<std::variant<boolean, WorkspaceSymbolOptions>> workspaceSymbolProvider;
        std::optional<std::variant<boolean, InlineCompletionOptions>> inlineCompletionProvider;
        std::optional<TextDocument> textDocument;
        std::optional<Workspace> workspace;
        std::optional<LSPAny> experimental;
    };

    struct InitializeResult
    {
        struct ServerInfo
        {
            string name;
            std::optional<string> version;
        };

        ServerCapabilities capabilities;
        ServerInfo serverInfo;
    };

    struct InitializeError
    {
        boolean retry;
    };

    struct InitializeParams : WorkDoneProgressParams
    {
        struct ClientInfo
        {
            string name;
            std::optional<string> version;
        };

        std::optional<integer> processId;
        std::optional<ClientInfo> clientInfo;
        std::optional<string> locale;
        std::optional<string> rootPath;
        std::optional<DocumentUri> rootUri;
        std::optional<LSPAny> initializationOptions;
        std::optional<ClientCapabilities> capabilities;
        TraceValue trace;
        std::optional<std::vector<WorkspaceFolder>> workspaceFolders;
    };

}
