#ifndef NVIM_HIGHLIGHT_DEFS_H
#define NVIM_HIGHLIGHT_DEFS_H

#include <inttypes.h>

#include "nvim/macros.h"
#include "nvim/types.h"

typedef int32_t RgbValue;

/// Highlighting attribute bits.
///
/// sign bit should not be used here, as it identifies invalid highlight
typedef enum {
  HL_INVERSE         = 0x01,
  HL_BOLD            = 0x02,
  HL_ITALIC          = 0x04,
  HL_UNDERLINE       = 0x08,
  HL_UNDERCURL       = 0x10,
  HL_STANDOUT        = 0x20,
  HL_STRIKETHROUGH   = 0x40,
  HL_NOCOMBINE       = 0x80,
  HL_BG_INDEXED    = 0x0100,
  HL_FG_INDEXED    = 0x0200,
  HL_DEFAULT       = 0x0400,
  HL_GLOBAL        = 0x0800,
} HlAttrFlags;

/// Stores a complete highlighting entry, including colors and attributes
/// for both TUI and GUI.
typedef struct attr_entry {
  int16_t rgb_ae_attr, cterm_ae_attr;  ///< HlAttrFlags
  RgbValue rgb_fg_color, rgb_bg_color, rgb_sp_color;
  int cterm_fg_color, cterm_bg_color;
  int hl_blend;
} HlAttrs;

#define HLATTRS_INIT (HlAttrs) { \
  .rgb_ae_attr = 0, \
  .cterm_ae_attr = 0, \
  .rgb_fg_color = -1, \
  .rgb_bg_color = -1, \
  .rgb_sp_color = -1, \
  .cterm_fg_color = 0, \
  .cterm_bg_color = 0, \
  .hl_blend = -1, \
}

/// Values for index in highlight_attr[].
/// When making changes, also update hlf_names below!
typedef enum {
  HLF_8 = 0,        // Meta & special keys listed with ":map", text that is
                    // displayed different from what it is
  HLF_EOB,        // after the last line in the buffer
  HLF_TERM,       // terminal cursor focused
  HLF_TERMNC,     // terminal cursor unfocused
  HLF_AT,          // @ characters at end of screen, characters that don't really exist in the text
  HLF_D,          // directories in CTRL-D listing
  HLF_E,          // error messages
  HLF_I,          // incremental search
  HLF_L,          // last search string
  HLF_M,          // "--More--" message
  HLF_CM,         // Mode (e.g., "-- INSERT --")
  HLF_N,          // line number for ":number" and ":#" commands
  HLF_LNA,        // LineNrAbove
  HLF_LNB,        // LineNrBelow
  HLF_CLN,        // current line number when 'cursorline' is set
  HLF_R,          // return to continue message and yes/no questions
  HLF_S,          // status lines
  HLF_SNC,        // status lines of not-current windows
  HLF_C,          // column to separate vertically split windows
  HLF_T,          // Titles for output from ":set all", ":autocmd" etc.
  HLF_V,          // Visual mode
  HLF_VNC,        // Visual mode, autoselecting and not clipboard owner
  HLF_W,          // warning messages
  HLF_WM,         // Wildmenu highlight
  HLF_FL,         // Folded line
  HLF_FC,         // Fold column
  HLF_ADD,        // Added diff line
  HLF_CHD,        // Changed diff line
  HLF_DED,        // Deleted diff line
  HLF_TXD,        // Text Changed in diff line
  HLF_SC,         // Sign column
  HLF_CONCEAL,    // Concealed text
  HLF_SPB,        // SpellBad
  HLF_SPC,        // SpellCap
  HLF_SPR,        // SpellRare
  HLF_SPL,        // SpellLocal
  HLF_PNI,        // popup menu normal item
  HLF_PSI,        // popup menu selected item
  HLF_PSB,        // popup menu scrollbar
  HLF_PST,        // popup menu scrollbar thumb
  HLF_TP,         // tabpage line
  HLF_TPS,        // tabpage line selected
  HLF_TPF,        // tabpage line filler
  HLF_CUC,        // 'cursorcolumn'
  HLF_CUL,        // 'cursorline'
  HLF_MC,         // 'colorcolumn'
  HLF_QFL,        // selected quickfix line
  HLF_0,          // Whitespace
  HLF_INACTIVE,   // NormalNC: Normal text in non-current windows
  HLF_MSGSEP,     // message separator line
  HLF_NFLOAT,     // Floating window
  HLF_MSG,        // Message area
  HLF_BORDER,     // Floating window border
  HLF_COUNT,  // MUST be the last one
} hlf_T;

EXTERN const char *hlf_names[] INIT(= {
  [HLF_8] = "SpecialKey",
  [HLF_EOB] = "EndOfBuffer",
  [HLF_TERM] = "TermCursor",
  [HLF_TERMNC] = "TermCursorNC",
  [HLF_AT] = "NonText",
  [HLF_D] = "Directory",
  [HLF_E] = "ErrorMsg",
  [HLF_I] = "IncSearch",
  [HLF_L] = "Search",
  [HLF_M] = "MoreMsg",
  [HLF_CM] = "ModeMsg",
  [HLF_N] = "LineNr",
  [HLF_LNA] = "LineNrAbove",
  [HLF_LNB] = "LineNrBelow",
  [HLF_CLN] = "CursorLineNr",
  [HLF_R] = "Question",
  [HLF_S] = "StatusLine",
  [HLF_SNC] = "StatusLineNC",
  [HLF_C] = "VertSplit",
  [HLF_T] = "Title",
  [HLF_V] = "Visual",
  [HLF_VNC] = "VisualNC",
  [HLF_W] = "WarningMsg",
  [HLF_WM] = "WildMenu",
  [HLF_FL] = "Folded",
  [HLF_FC] = "FoldColumn",
  [HLF_ADD] = "DiffAdd",
  [HLF_CHD] = "DiffChange",
  [HLF_DED] = "DiffDelete",
  [HLF_TXD] = "DiffText",
  [HLF_SC] = "SignColumn",
  [HLF_CONCEAL] = "Conceal",
  [HLF_SPB] = "SpellBad",
  [HLF_SPC] = "SpellCap",
  [HLF_SPR] = "SpellRare",
  [HLF_SPL] = "SpellLocal",
  [HLF_PNI] = "Pmenu",
  [HLF_PSI] = "PmenuSel",
  [HLF_PSB] = "PmenuSbar",
  [HLF_PST] = "PmenuThumb",
  [HLF_TP] = "TabLine",
  [HLF_TPS] = "TabLineSel",
  [HLF_TPF] = "TabLineFill",
  [HLF_CUC] = "CursorColumn",
  [HLF_CUL] = "CursorLine",
  [HLF_MC] = "ColorColumn",
  [HLF_QFL] = "QuickFixLine",
  [HLF_0] = "Whitespace",
  [HLF_INACTIVE] = "NormalNC",
  [HLF_MSGSEP] = "MsgSeparator",
  [HLF_NFLOAT] = "NormalFloat",
  [HLF_MSG] = "MsgArea",
  [HLF_BORDER] = "FloatBorder",
});


EXTERN int highlight_attr[HLF_COUNT];       // Highl. attr for each context.
EXTERN int highlight_attr_last[HLF_COUNT];  // copy for detecting changed groups
EXTERN int highlight_user[9];                   // User[1-9] attributes
EXTERN int highlight_stlnc[9];                  // On top of user
EXTERN int cterm_normal_fg_color INIT(= 0);
EXTERN int cterm_normal_bg_color INIT(= 0);
EXTERN RgbValue normal_fg INIT(= -1);
EXTERN RgbValue normal_bg INIT(= -1);
EXTERN RgbValue normal_sp INIT(= -1);

typedef enum {
  kHlUnknown,
  kHlUI,
  kHlSyntax,
  kHlTerminal,
  kHlCombine,
  kHlBlend,
  kHlBlendThrough,
} HlKind;

typedef struct {
  HlAttrs attr;
  HlKind kind;
  int id1;
  int id2;
  int winid;
} HlEntry;

typedef struct {
  int ns_id;
  int syn_id;
} ColorKey;
#define ColorKey(n, s) (ColorKey) { .ns_id = (int)(n), .syn_id = (s) }

typedef struct {
  int attr_id;
  int link_id;
  int version;
  bool is_default;
} ColorItem;
#define COLOR_ITEM_INITIALIZER { .attr_id = -1, .link_id = -1, \
                                 .version = -1, .is_default = false }


#endif  // NVIM_HIGHLIGHT_DEFS_H
