#pragma once
#include "LibLsp/lsp/method_type.h"

#include <stdexcept>

#include "LibLsp/JsonRpc/message.h"
#include "LibLsp/lsp/lsDocumentUri.h"
#include "LibLsp/lsp/lsAny.h"
#include "LibLsp/lsp/extention/jdtls/searchSymbols.h"

/**
* Capabilities specific to `WorkspaceEdit`s
*/

//New in version 3.13: ResourceOperationKind and FailureHandlingKind and the client capability workspace.workspaceEdit.
//resourceOperations as well as workspace.workspaceEdit.failureHandling.

//The capabilities of a workspace edit has evolved over the time.
//Clients can describe their support using the following client capability :

struct lschangeAnnotationSupport
{
   /**
        * Whether the client groups edits with equal labels into tree nodes,
        * for instance all edits labelled with "Changes in Strings" would
        * be a tree node.
        */
   optional<bool> groupsOnLabel;
   MAKE_SWAP_METHOD(lschangeAnnotationSupport, groupsOnLabel)
};
MAKE_REFLECT_STRUCT(lschangeAnnotationSupport, groupsOnLabel)

struct WorkspaceEditCapabilities
{
   /**
        * The client supports versioned document changes in `WorkspaceEdit`s
        */
   optional<bool> documentChanges;

   /**
        * The client supports resource changes
        * in `WorkspaceEdit`s.
        *
        * @deprecated Since LSP introduces resource operations, use {link #resourceOperations}
        */

   optional<bool> resourceChanges;

   /**
        * The resource operations the client supports. Clients should at least
        * support 'create', 'rename' and 'delete' files and folders.
        *
        * @since 3.13.0
        */
   optional<std::vector<std::string>> resourceOperations;

   /**
        * The failure handling strategy of a client if applying the workspace edit
        * fails.
        *
        * See {@link FailureHandlingKind} for allowed values.
        */
   optional<std::string> failureHandling;

   /**
        * Whether the client normalizes line endings to the client specific
        * setting.
        * If set to `true` the client will normalize line ending characters
        * in a workspace edit to the client specific new line character(s).
        *
        * @since 3.16.0
        */
   optional<bool> normalizesLineEndings;
   ;

   /**
        * Whether the client in general supports change annotations on text edits,
        * create file, rename file and delete file changes.
        *
        * @since 3.16.0
        */
   optional<lschangeAnnotationSupport> changeAnnotationSupport;

   MAKE_SWAP_METHOD(
       WorkspaceEditCapabilities, documentChanges, resourceChanges, resourceOperations, failureHandling,
       normalizesLineEndings, changeAnnotationSupport
   )
};
MAKE_REFLECT_STRUCT(
   WorkspaceEditCapabilities, documentChanges, resourceChanges, resourceOperations, failureHandling,
   normalizesLineEndings, changeAnnotationSupport
)

struct DynamicRegistrationCapabilities
{
   // Did foo notification supports dynamic registration.
   optional<bool> dynamicRegistration;

   MAKE_SWAP_METHOD(DynamicRegistrationCapabilities, dynamicRegistration);
};

MAKE_REFLECT_STRUCT(DynamicRegistrationCapabilities, dynamicRegistration);

struct InlayHintLazyProperties
{
   optional<std::vector<std::string>> properties;

   MAKE_SWAP_METHOD(InlayHintLazyProperties, properties)
};

MAKE_REFLECT_STRUCT(InlayHintLazyProperties, properties)

struct InlayHintClientCapabilities
{
   // Whether inlay hints support dynamic registration.
   optional<bool> dynamicRegistration;

   optional<InlayHintLazyProperties> resolveSupport;

   MAKE_SWAP_METHOD(InlayHintClientCapabilities, dynamicRegistration, resolveSupport);
};

MAKE_REFLECT_STRUCT(InlayHintClientCapabilities, dynamicRegistration, resolveSupport)

// Workspace specific client capabilities.
struct SymbolKindCapabilities
{
   optional<std::vector<lsSymbolKind>> valueSet;

   MAKE_SWAP_METHOD(SymbolKindCapabilities, valueSet)
};
MAKE_REFLECT_STRUCT(SymbolKindCapabilities, valueSet)

struct SymbolCapabilities : public DynamicRegistrationCapabilities
{
   /**
        * Specific capabilities for the `SymbolKind` in the `workspace/symbol` request.
        */
   optional<SymbolKindCapabilities> symbolKind;

   MAKE_SWAP_METHOD(SymbolCapabilities, symbolKind, dynamicRegistration)
};
MAKE_REFLECT_STRUCT(SymbolCapabilities, symbolKind, dynamicRegistration)

struct lsFileOperations
{
   /**
* Whether the client supports dynamic registration for file
* requests/notifications.
*/
   optional<bool> dynamicRegistration;

   /**
        * The client has support for sending didCreateFiles notifications.
        */
   optional<bool> didCreate;

   /**
        * The client has support for sending willCreateFiles requests.
        */
   optional<bool> willCreate;

   /**
        * The client has support for sending didRenameFiles notifications.
        */
   optional<bool> didRename;

   /**
        * The client has support for sending willRenameFiles requests.
        */
   optional<bool> willRename;

   /**
        * The client has support for sending didDeleteFiles notifications.
        */
   optional<bool> didDelete;

   /**
        * The client has support for sending willDeleteFiles requests.
        */
   optional<bool> willDelete;
   MAKE_SWAP_METHOD(
       lsFileOperations, dynamicRegistration, didCreate, willCreate, didRename, willRename, didDelete, willDelete
   )
};
MAKE_REFLECT_STRUCT(
   lsFileOperations, dynamicRegistration, didCreate, willCreate, didRename, willRename, didDelete, willDelete
)

struct lsWorkspaceClientCapabilites
{
   // The client supports applying batch edits to the workspace.
   optional<bool> applyEdit;

   // Capabilities specific to `WorkspaceEdit`s
   optional<WorkspaceEditCapabilities> workspaceEdit;

   // Capabilities specific to the `workspace/didChangeConfiguration`
   // notification.
   optional<DynamicRegistrationCapabilities> didChangeConfiguration;

   // Capabilities specific to the `workspace/didChangeWatchedFiles`
   // notification.
   optional<DynamicRegistrationCapabilities> didChangeWatchedFiles;

   // Capabilities specific to the `workspace/symbol` request.
   optional<SymbolCapabilities> symbol;

   // Capabilities specific to the `workspace/executeCommand` request.
   optional<DynamicRegistrationCapabilities> executeCommand;

   /**
* The client has support for workspace folders.
*
* Since 3.6.0
*/
   optional<bool> workspaceFolders;

   /**
  * The client supports `workspace/configuration` requests.
  *
  * Since 3.6.0
  */
   optional<bool> configuration;

   /**
                * Capabilities specific to the semantic token requests scoped to the
                * workspace.
                *
                * @since 3.16.0
                */
   optional<DynamicRegistrationCapabilities> semanticTokens;

   /**
  * Capabilities specific to the code lens requests scoped to the
  * workspace.
  *
  * @since 3.16.0
  */
   optional<DynamicRegistrationCapabilities> codeLens;

   /**
  * The client has support for file requests/notifications.
  *
  * @since 3.16.0
  */
   optional<lsFileOperations> fileOperations;

   MAKE_SWAP_METHOD(
       lsWorkspaceClientCapabilites, applyEdit, workspaceEdit, didChangeConfiguration, didChangeWatchedFiles, symbol,
       executeCommand, workspaceFolders, configuration, semanticTokens, codeLens, fileOperations
   )
};

MAKE_REFLECT_STRUCT(
   lsWorkspaceClientCapabilites, applyEdit, workspaceEdit, didChangeConfiguration, didChangeWatchedFiles, symbol,
   executeCommand, workspaceFolders, configuration, semanticTokens, codeLens, fileOperations
)