local M = {
  'gruvbox-community/gruvbox',
  lazy = false,
  priority = 999,
}

function M.config()
  local function normalizeTerminal() -- {{{
    vim.g.terminal_color_0 = 0
    vim.g.terminal_color_1 = 1
    vim.g.terminal_color_2 = 2
    vim.g.terminal_color_3 = 3
    vim.g.terminal_color_4 = 4
    vim.g.terminal_color_5 = 5
    vim.g.terminal_color_6 = 6
    vim.g.terminal_color_7 = 7
    vim.g.terminal_color_8 = 8
    vim.g.terminal_color_9 = 9
    vim.g.terminal_color_10 = 10
    vim.g.terminal_color_11 = 11
    vim.g.terminal_color_12 = 12
    vim.g.terminal_color_13 = 13
    vim.g.terminal_color_14 = 14
    vim.g.terminal_color_15 = 15
  end                                        -- }}}

  local function normalizeCmpKindHighlight() -- {{{
    vim.api.nvim_set_hl(0, 'CmpItemKindClass', { link = 'Identifier' })
    vim.api.nvim_set_hl(0, 'CmpItemKindConstant', { link = 'Constant' })
    vim.api.nvim_set_hl(0, 'CmpItemKindConstructor', { link = 'Special' })
    vim.api.nvim_set_hl(0, 'CmpItemKindEnum', { link = 'Identifier' })
    vim.api.nvim_set_hl(0, 'CmpItemKindEnumMember', { link = 'String' })
    vim.api.nvim_set_hl(0, 'CmpItemKindField', { link = 'Identifier' })
    vim.api.nvim_set_hl(0, 'CmpItemKindFile', { link = 'File' })
    vim.api.nvim_set_hl(0, 'CmpItemKindFolder', { link = 'Directory' })
    vim.api.nvim_set_hl(0, 'CmpItemKindFunction', { link = 'Function' })
    vim.api.nvim_set_hl(0, 'CmpItemKindInterface', { link = 'Identifier' })
    vim.api.nvim_set_hl(0, 'CmpItemKindKeyword', { link = 'Keyword' })
    vim.api.nvim_set_hl(0, 'CmpItemKindMethod', { link = 'Function' })
    vim.api.nvim_set_hl(0, 'CmpItemKindModule', { link = 'Include' })
    vim.api.nvim_set_hl(0, 'CmpItemKindProperty', { link = 'Identifier' })
    vim.api.nvim_set_hl(0, 'CmpItemKindSnippet', { link = 'Special' })
    vim.api.nvim_set_hl(0, 'CmpItemKindStruct', { link = 'Identifier' })
    vim.api.nvim_set_hl(0, 'CmpItemKindText', { link = 'String' })
    vim.api.nvim_set_hl(0, 'CmpItemKindTypeParameter', { link = 'Identifier' })
    vim.api.nvim_set_hl(0, 'CmpItemKindValue', { link = 'String' })
    vim.api.nvim_set_hl(0, 'CmpItemKindVariable', { link = 'Identifier' })
  end -- }}}

  local function copyFg(to, from, opts)
    local hl = vim.api.nvim_get_hl(0, { name = from })

    local o = vim.tbl_extend('force', { ctermfg = hl.foreground, fg = hl.foreground }, opts or {})
    vim.api.nvim_set_hl(0, to, o)
  end

  local function clear(hl)
    vim.api.nvim_set_hl(0, hl, {})
  end

  local function link(hl, to)
    vim.api.nvim_set_hl(0, hl, { link = to })
  end

  local function normalizeTSHighlight() --- {{{
    link('@class', 'Type')
    link('@interface', 'Type')
    link('@namespace', 'Type')
    link('@event', 'Type')

    link('@type.qualifier', 'Keyword')
    link('@storageclass', 'Keyword')
    link('@modifier', 'Keyword')

    link('@attribute', 'PreProc')

    link('@tag.attribute', 'Identifier')
    link('@tag.delimiter', 'Delimiter')
    link('@variable', 'Identifier')
  end                                        -- }}}

  local function customLinks()
    copyFg('Function', 'Normal')
    copyFg('Operator', 'Normal')
  end

  local augr = vim.api.nvim_create_augroup('config_colorscheme', {});
  vim.api.nvim_create_autocmd('Colorscheme', {
    group = augr,
    pattern = '*',
    callback = function()
      normalizeTSHighlight()
      customLinks()
      normalizeTerminal()
      normalizeCmpKindHighlight()
    end,
  })

  vim.api.nvim_create_autocmd('Colorscheme', {
    group = augr,
    pattern = 'gruvbox',
    callback = function()
      local gr = require('configs.colors')

      link('Directory', 'GruvboxGreen')
      link('TelescopeSelection', 'GruvboxOrangeSign')
      link('TelescopeMatching', 'GruvboxAqua')

      link('NeoTreeGitAdded', 'GruvboxGreen')
      link('NeoTreeGitDeleted', 'GruvboxRed')
      link('NeoTreeGitModified', 'GruvboxOrange')

      link('CmpItemAbbrMatch', 'GruvboxAquaBold')
      link('CmpItemAbbrMatchFuzzy', 'GruvboxAquaBold')

      link('FloatBorder', 'GruvBoxFg1')

      link('NonText', 'GruvboxBg3') -- make it more bright

      local linenr_style = { 'underdotted' }
      if vim.fn.has('nvim-0.9') then
        linenr_style = {}
      end

      -- link('@tag.delimiter.xml', 'xmlTag')
      -- link('@tag.xml', 'xmlTagName')
      -- link('@tag.attribute.xml', 'xmlAttrib')
      --
      -- link('@tag.delimiter.html', 'htmlTag')
      -- link('@tag.html', 'htmlTagName')
      -- link('@tag.attribute.html', 'htmlArg')

      link('WinBar', 'StatusLine')
      link('WinBarNC', 'StatusLineNC')
      gr:hl('LineNr', 'gray', 'dark0_hard', linenr_style)
      gr:hl('LspCodeLens', 'gray', nil, { 'italic' })

      gr:hl('IndentBlanklineContextChar', 'orange', nil, { 'nocombine' })

      link('DiagnosticSignOk', 'GruvboxGreenSign')

      gr:hl('DiagnosticVirtualTextError', 'error', nil, { 'italic' })
      gr:hl('DiagnosticVirtualTextWarn', 'warn', nil, { 'italic' })
      gr:hl('DiagnosticVirtualTextInfo', 'info', nil, { 'italic' })
      gr:hl('DiagnosticVirtualTextHint', 'hint', nil, { 'italic' })
      gr:hl('DiagnosticVirtualTextOk', 'ok', nil, { 'italic' })

      gr:hl('Function', 'light1', nil, {})
      gr:hl('Operator', 'light1', nil, {})
      link('Identifier', 'GruvboxBlue')
      link('Punctuation', 'GruvboxOrange')

      gr:hl('Bold', nil, nil, { 'bold' }, {})
      gr:hl('Strikethrough', nil, nil, { 'strikethrough' }, {})
      gr:hl('Underlined', nil, nil, { 'underline' }, {})

      gr:hl('@text.uri', 'bright_blue', nil, { 'underline' }, {})
      gr:hl('@text.emphasis', nil, nil, { 'italic' }, {})

      link('DiagnosticError', 'GruvboxRed')
      link('DiagnosticWarn', 'GruvboxYellow')
      link('DiagnosticInfo', 'GruvboxBlue')
      link('DiagnosticHint', 'GruvboxAqua')
      link('DiagnosticOk', 'GruvboxGreen')
      link('RedrawDebugClear', 'GruvboxAqua')
      link('RedrawDebugComposed', 'GruvboxGreen')
      link('RedrawDebugRecompose', 'GruvboxRed')
      link('DiagnosticFloatingError', 'DiagnosticError')
      link('DiagnosticFloatingWarn', 'DiagnosticWarn')
      link('DiagnosticFloatingInfo', 'DiagnosticInfo')
      link('DiagnosticFloatingHint', 'DiagnosticHint')
      link('DiagnosticFloatingOk', 'DiagnosticOk')
      link('DiagnosticUnderlineOk', 'GruvboxAquaUnderline')
      link('DiagnosticUnderlineError', 'GruvboxRedUnderline')
      link('DiagnosticUnderlineWarn', 'GruvboxYellowUnderline')
      link('DiagnosticUnderlineInfo', 'GruvboxBlueUnderline')
      link('DiagnosticUnderlineHint', 'GruvboxAquaUnderline')

      gr:hl('DiagnosticDeprecated', nil, nil, { 'strikethrough' }, { sp = 'red' })

      gr:hl('NormalFloat', 'light0_hard', 'dark1', {}, nil)

      -- gr:hl('GitSignsAddLine', nil, 'faded_green', {})
      -- vim.fn.sign_define('GitSignsAdd', { text = '│', texthl = 'GitSignsAdd', linehl = 'GitSignsAddLine', culhl='CursorLine' })
      link('DapUINormal', 'Normal')
      link('DapUIVariable', 'Identifier')
      link('DapUIScope', 'GruvboxAqua')
      link('DapUIType', 'Type')
      link('DapUIValue', 'GruvboxFg1')
      link('DapUIModifiedValue', 'GruvboxAquaBold')
      link('DapUIDecoration', 'GruvboxAqua')
      link('DapUIThread', 'GruvboxGreen')
      link('DapUIStoppedThread', 'GruvboxAqua')
      link('DapUIFrameName', 'GruvboxFg1')
      link('DapUISource', 'GruvboxPurple')
      link('DapUILineNumber', 'GruvboxAqua')
      link('DapUIFloatNormal', 'NormalFloat')
      link('DapUIFloatBorder', 'GruvboxAqua')
      link('DapUIWatchesEmpty', 'GruvboxRed')
      link('DapUIWatchesValue', 'GruvboxGreen')
      link('DapUIWatchesError', 'GruvboxRed')
      link('DapUIBreakpointsPath', 'GruvboxAqua')
      link('DapUIBreakpointsInfo', 'GruvboxGreen')
      link('DapUIBreakpointsCurrentLine', 'GruvboxGreenBold')
      link('DapUIBreakpointsLine', 'DapUILineNumber')
      link('DapUIBreakpointsDisabledLine', 'Comment')
      link('DapUICurrentFrameName', 'DapUIBreakpointsCurrentLine')
      link('DapUIStepOver', 'GruvboxAqua')
      link('DapUIStepInto', 'GruvboxAqua')
      link('DapUIStepBack', 'GruvboxAqua')
      link('DapUIStepOut', 'GruvboxAqua')
      link('DapUIStop', 'GruvboxRed')
      link('DapUIPlayPause', 'GruvboxGreen')
      link('DapUIRestart', 'GruvboxGreen')
      link('DapUIUnavailable', 'Comment')
      link('DapUIWinSelect', 'GruvboxAquaBold')
      link('DapUIEndofBuffer', 'EndofBuffer')
    end,
  })

  vim.api.nvim_create_autocmd('ColorschemePre', {
    group = augr,
    pattern = '*',
    callback = function()
      vim.fn.sign_define('DiagnosticSignError', { text = ' ', texthl = 'DiagnosticSignError' })
      vim.fn.sign_define('DiagnosticSignWarn', { text = ' ', texthl = 'DiagnosticSignWarn' })
      vim.fn.sign_define('DiagnosticSignInfo', { text = ' ', texthl = 'DiagnosticSignInfo' })
      vim.fn.sign_define('DiagnosticSignHint', { text = '󰌵', texthl = 'DiagnosticSignHint' })
    end,
  })

  local term = vim.env.TERM
  if (term ~= 'linux' or vim.g.neoray)
  then
    vim.o.termguicolors = true
    vim.g.gruvbox_contrast_dark = 'hard'
    vim.cmd.colorscheme('gruvbox')
  end
end

return M

-- return {
--   'ellisonleao/gruvbox.nvim',
--   lazy = false,
--   priority = 999,
--   config = function()
--     local g = require('gruvbox')
--     local p = require('gruvbox.palette').colors
--     local overrides = {
--       Directory                  = { link = 'GruvboxGreen' },
--       ['@variable']              = { link = 'GruvboxBlue' },
--       Function                   = { link = 'GruvboxFg1' },
--       Operator                   = { link = 'GruvboxFg1' },
--       IndentBlanklineContextChar = { fg = p.neutral_orange },
--
--       NeoTreeGitAdded            = { link = 'GruvboxGreen' },
--       NeoTreeGitDeleted          = { link = 'GruvboxRed' },
--       NeoTreeGitModified         = { link = 'GruvboxOrange' },
--       NeoTreeGitUntracked        = { link = 'GruvboxOrange' },
--
--       CmpItemAbbrMatch           = { link = 'GruvboxAquaBold' },
--       CmpItemAbbrMatchFuzzy      = { link = 'GruvboxAquaBold' },
--
--       CmpItemKindClass           = { link = 'Identifier' },
--       CmpItemKindConstant        = { link = 'Constant' },
--       CmpItemKindConstructor     = { link = 'Special' },
--       CmpItemKindEnum            = { link = 'Identifier' },
--       CmpItemKindEnumMember      = { link = 'String' },
--       CmpItemKindField           = { link = 'Identifier' },
--       CmpItemKindFile            = { link = 'File' },
--       CmpItemKindFolder          = { link = 'Directory' },
--       CmpItemKindFunction        = { link = 'Function' },
--       CmpItemKindInterface       = { link = 'Identifier' },
--       CmpItemKindKeyword         = { link = 'Keyword' },
--       CmpItemKindMethod          = { link = 'Function' },
--       CmpItemKindModule          = { link = 'Include' },
--       CmpItemKindProperty        = { link = 'Identifier' },
--       CmpItemKindSnippet         = { link = 'Special' },
--       CmpItemKindStruct          = { link = 'Identifier' },
--       CmpItemKindText            = { link = 'String' },
--       CmpItemKindTypeParameter   = { link = 'Identifier' },
--       CmpItemKindValue           = { link = 'String' },
--       CmpItemKindVariable        = { link = 'Identifier' },
--     }
--
--     local augr = vim.api.nvim_create_augroup('config_colorscheme', {});
--     vim.api.nvim_create_autocmd('ColorschemePre', {
--       group = augr,
--       pattern = '*',
--       callback = function()
--         vim.fn.sign_define('DiagnosticSignError', { text = ' ', texthl = 'DiagnosticSignError' })
--         vim.fn.sign_define('DiagnosticSignWarn', { text = ' ', texthl = 'DiagnosticSignWarn' })
--         vim.fn.sign_define('DiagnosticSignInfo', { text = ' ', texthl = 'DiagnosticSignInfo' })
--         vim.fn.sign_define('DiagnosticSignHint', { text = '󰌵', texthl = 'DiagnosticSignHint' })
--       end,
--     })
--
--     g.setup({ overrides = overrides })
--
--     vim.cmd.colorscheme('gruvbox')
--   end,
-- }

