#pragma once
#include <optional>
#include "lsRange.h"
#include "lsTextEdit.h"
#include "lsDocumentUri.h"

#include "lsResponseError.h"
#include "location_type.h"

#include "LibLsp/JsonRpc/RequestInMessage.h"
#include "LibLsp/JsonRpc/lsResponseMessage.h"

enum class lsDiagnosticSeverity
{
   // Reports an error.
   Error = 1,
   // Reports a warning.
   Warning = 2,
   // Reports an information.
   Information = 3,
   // Reports a hint.
   Hint = 4
};
MAKE_REFLECT_TYPE_PROXY(lsDiagnosticSeverity);

/**
* The diagnostic tags.
*
* @since 3.15.0
*/
enum class DiagnosticTag : uint8_t
{

   /**
        * Unused or unnecessary code.
        *
        * Clients are allowed to render diagnostics with this tag faded out instead of having
        * an error squiggle.
        */
   Unnecessary = (1),

   /**
        * Deprecated or obsolete code.
        *
        * Clients are allowed to rendered diagnostics with this tag strike through.
        */
   Deprecated = (2),
};
MAKE_REFLECT_TYPE_PROXY(DiagnosticTag);

/**
* Represents a related message and source code location for a diagnostic. This should be
* used to point to code locations that cause or related to a diagnostics, e.g when duplicating
* a symbol in a scope.
*
* Since 3.7.0
*/

struct DiagnosticRelatedInformation
{
   /**
        * The location of this related diagnostic information.
        */

   lsLocation location;

   /**
        * The message of this related diagnostic information.
        */

   std::string message;

   MAKE_SWAP_METHOD(DiagnosticRelatedInformation, location, message)
};
MAKE_REFLECT_STRUCT(DiagnosticRelatedInformation, location, message)
/**
* Structure to capture a description for an error code.
*
* @since 3.16.0
*/
struct DiagnosticCodeDescription
{
   /**
        * An URI to open with more information about the diagnostic error.
        */
   std::string href;
   MAKE_SWAP_METHOD(DiagnosticCodeDescription, href)
};
MAKE_REFLECT_STRUCT(DiagnosticCodeDescription, href)

//Represents a diagnostic, such as a compiler error or warning.Diagnostic objects are only valid in the scope of a resource.
struct lsDiagnostic
{
   // The range at which the message applies.
   lsRange range;

   // The diagnostic's severity. Can be omitted. If omitted it is up to the
   // client to interpret diagnostics as error, warning, info or hint.
   optional<lsDiagnosticSeverity> severity;

   // The diagnostic's code. Can be omitted.
   optional<std::pair<optional<std::string>, optional<int>>> code;

   optional<DiagnosticCodeDescription> codeDescription;
   // A human-readable string describing the source of this
   // diagnostic, e.g. 'typescript' or 'super lint'.
   optional<std::string> source;

   // The diagnostic's message.
   std::string message;

   // Non-serialized set of fixits.
   std::vector<lsTextEdit> fixits_;

   /**
  * Additional metadata about the diagnostic.
  *
  * @since 3.15.0
  */
   optional<std::vector<DiagnosticTag>> tags;

   /**
* An array of related diagnostic information, e.g. when symbol-names within a scope collide
* all definitions can be marked via this property.
*
* Since 3.7.0
*/
   optional<std::vector<DiagnosticRelatedInformation>> relatedInformation;

   /**
  * A data entry field that is preserved between a
  * `textDocument/publishDiagnostics` notification and
  * `textDocument/codeAction` request.
  *
  * @since 3.16.0
  */
   optional<lsp::Any> data;
   bool operator==(lsDiagnostic const& rhs) const;
   bool operator!=(lsDiagnostic const& rhs) const;

   MAKE_SWAP_METHOD(lsDiagnostic, range, severity, code, codeDescription, source, message, tags, data)
};
MAKE_REFLECT_STRUCT(lsDiagnostic, range, severity, code, codeDescription, source, message, tags, data)

struct Rsp_Error : ResponseError<lsResponseError, Rsp_Error>
{

   MAKE_SWAP_METHOD(Rsp_Error, jsonrpc, id, error)
};
MAKE_REFLECT_STRUCT(Rsp_Error, jsonrpc, id, error)