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

enum class lsSymbolKind : uint8_t
{
   Unknown = 0,

   File = 1,
   Module = 2,
   Namespace = 3,
   Package = 4,
   Class = 5,
   Method = 6,
   Property = 7,
   Field = 8,
   Constructor = 9,
   Enum = 10,
   Interface = 11,
   Function = 12,
   Variable = 13,
   Constant = 14,
   String = 15,
   Number = 16,
   Boolean = 17,
   Array = 18,
   Object = 19,
   Key = 20,
   Null = 21,
   EnumMember = 22,
   Struct = 23,
   Event = 24,
   Operator = 25,

   // For C++, this is interpreted as "template parameter" (including
   // non-type template parameters).
   TypeParameter = 26,

   // cquery extensions
   // See also https://github.com/Microsoft/language-server-protocol/issues/344
   // for new SymbolKind clang/Index/IndexSymbol.h clang::index::SymbolKind
   TypeAlias = 252,
   Parameter = 253,
   StaticMethod = 254,
   Macro = 255,
};
MAKE_REFLECT_TYPE_PROXY(lsSymbolKind);

typedef lsSymbolKind SymbolKind;

// A document highlight kind.
enum class lsDocumentHighlightKind
{
   // A textual occurrence.
   Text = 1,
   // Read-access of a symbol, like reading a variable.
   Read = 2,
   // Write-access of a symbol, like writing to a variable.
   Write = 3
};
MAKE_REFLECT_TYPE_PROXY(lsDocumentHighlightKind);

// A document highlight is a range inside a text document which deserves
// special attention. Usually a document highlight is visualized by changing
// the background color of its range.
struct lsDocumentHighlight
{
   // The range this highlight applies to.
   lsRange range;

   // The highlight kind, default is DocumentHighlightKind.Text.
   optional<lsDocumentHighlightKind> kind;

   MAKE_SWAP_METHOD(lsDocumentHighlight, range, kind)
};
MAKE_REFLECT_STRUCT(lsDocumentHighlight, range, kind);

struct lsSymbolInformation
{

   /**
* The name of this symbol.
*/
   std::string name;
   /**
  * The kind of this symbol.
  */
   lsSymbolKind kind;
   /**
* Indicates if this symbol is deprecated.
*/
   optional<bool> deprecated;
   /**
  * The location of this symbol. The location's range is used by a tool
  * to reveal the location in the editor. If the symbol is selected in the
  * tool the range's start information is used to position the cursor. So
  * the range usually spans more then the actual symbol's name and does
  * normally include things like visibility modifiers.
  *
  * The range doesn't have to denote a node range in the sense of a abstract
  * syntax tree. It can therefore not be used to re-construct a hierarchy of
  * the symbols.
  */
   lsLocation location;
   /**
* The name of the symbol containing this symbol. This information is for
* user interface purposes (e.g. to render a qualifier in the user interface
* if necessary). It can't be used to re-infer a hierarchy for the document
* symbols.
*/
   optional<std::string> containerName;

   MAKE_SWAP_METHOD(lsSymbolInformation, name, kind, deprecated, location, containerName);
};
MAKE_REFLECT_STRUCT(lsSymbolInformation, name, kind, deprecated, location, containerName);

struct lsDocumentSymbol
{
   /**
        * The name of this symbol.
        */

   std::string name;

   /**
        * The kind of this symbol.
        */

   lsSymbolKind kind = lsSymbolKind::Unknown;

   /**
        * The range enclosing this symbol not including leading/trailing whitespace but everything else
        * like comments. This information is typically used to determine if the clients cursor is
        * inside the symbol to reveal in the symbol in the UI.
        */

   lsRange range;

   /**
        * The range that should be selected and revealed when this symbol is being picked, e.g the name of a function.
        * Must be contained by the `range`.
        */

   lsRange selectionRange;

   /**
        * More detail for this symbol, e.g the signature of a function. If not provided the
        * name is used.
        */
   optional<std::string> detail;

   /**
        * Indicates if this symbol is deprecated.
        */
   optional<bool> deprecated;

   /**
        * Children of this symbol, e.g. properties of a class.
        */
   optional<std::vector<lsDocumentSymbol>> children;

   //internal use
   int flags = 0;

   MAKE_SWAP_METHOD(lsDocumentSymbol, name, kind, range, selectionRange, detail, deprecated, children, flags);
};
MAKE_REFLECT_STRUCT(lsDocumentSymbol, name, kind, range, selectionRange, detail, deprecated, children, flags);