{ config, pkgs, ... }:

{
  home = {
    sessionVariables = {
      EDITOR = "nvim";
      VISUAL = "nvim";
    };
  };

  programs.neovim = {
    enable = true;
    viAlias = true;
    vimAlias = true;
    extraPackages = with pkgs; [
      nodePackages.prettier
      nodePackages.pyright
      rnix-lsp
      rust-analyzer
      cmake-format
      clang-tools
      rustfmt
      nixfmt
      shfmt
    ];
    plugins = with pkgs.vimPlugins; [
      vim-nix
      molokai
      vim-airline
      vim-airline-themes
      vim-lsp
      vim-indent-guides
      vim-signify
      vim-fugitive
      vimtex
      neoformat
      nvim-lspconfig
      vim-vsnip
      nvim-cmp
      cmp-nvim-lsp
      (nvim-treesitter.withPlugins (_: pkgs.tree-sitter.allGrammars))
      nvim-treesitter-textobjects
      minimap-vim
    ];

    extraConfig = ''
        " syntax
        syntax enable

        " color themes
        set termguicolors
        colorscheme molokai

        " wildcard mode
        set wildmode=longest:full,full

        " remapping popup menu (command autocompletion)
        cnoremap <expr> <up> pumvisible() ? "<C-p>" : "<up>"
        cnoremap <expr> <down> pumvisible() ? "<C-n>" : "<down>"
        cnoremap <expr> <CR> pumvisible() ? "<C-e>":"<CR>"
        
        " set line numbers
        set number

        " enable indent guides
        let g:indent_guides_enable_on_vim_startup = 1

        " Highlight row and column
        set cul
        set cuc

        " Fix for code not being aligned if between comment blocks
        set cindent cinkeys-=0#
        set expandtab shiftwidth=2 tabstop=2 softtabstop=2

        " Enable alignment
        let g:neoformat_basic_format_align = 1

        " Enable tab to spaces conversion
        let g:neoformat_basic_format_retab = 1

        " Enable trimmming of trailing whitespace
        let g:neoformat_basic_format_trim = 1

        " Config minimap
        let g:minimap_width = 10
        let g:minimap_auto_start = 1
        let g:minimap_auto_start_win_enter = 1

        lua << EOF

        -- Setup leap-nvim keymappings
        require('leap').add_default_mappings()

        ------------------
        -- Setup nvim-cmp.
        ------------------

        -- Set completeopt to have a better completion experience
        vim.o.completeopt = 'menuone,noselect'

        local cmp = require'cmp'

        cmp.setup({
          snippet = {
            -- REQUIRED - you must specify a snippet engine
            expand = function(args)
              vim.fn["vsnip#anonymous"](args.body) -- For `vsnip` users.
            end,
          },
          mapping = {
            ['<C-b>'] = cmp.mapping(cmp.mapping.scroll_docs(-4), { 'i', 'c' }),
            ['<C-f>'] = cmp.mapping(cmp.mapping.scroll_docs(4), { 'i', 'c' }),
            ['<C-Space>'] = cmp.mapping(cmp.mapping.complete(), { 'i', 'c' }),
            ['<C-y>'] = cmp.config.disable, -- Specify `cmp.config.disable` if you want to remove the default `<C-y>` mapping.
            ['<C-e>'] = cmp.mapping({
              i = cmp.mapping.abort(),
              c = cmp.mapping.close(),
            }),
            ['<CR>'] = cmp.mapping.confirm({ select = true }), -- Accept currently selected item. Set `select` to `false` to only confirm explicitly selected items.
          },
          sources = cmp.config.sources({
            { name = 'nvim_lsp' },
            { name = 'vsnip' }, -- For vsnip users.
          }, {
            { name = 'buffer' },
          })
        })

        -- Use buffer source for `/` (if you enabled `native_menu`, this won't work anymore).
        cmp.setup.cmdline('/', {
          sources = {
            { name = 'buffer' }
          }
        })

        -- Use cmdline & path source for ':' (if you enabled `native_menu`, this won't work anymore).
        cmp.setup.cmdline(':', {
          sources = cmp.config.sources({
            { name = 'path' }
          }, {
            { name = 'cmdline' }
          })
        })

        -- Setup lspconfig.
        local capabilities = require('cmp_nvim_lsp').update_capabilities(vim.lsp.protocol.make_client_capabilities())

        --------------
        -- LSP Servers
        --------------

        require'lspconfig'.pyright.setup{
          capabilities = capabilities
        }
        require'lspconfig'.rust_analyzer.setup{
          capabilities = capabilities
        }
        require'lspconfig'.rnix.setup{
          capabilities = capabilities
        }
        require'lspconfig'.clangd.setup{
          capabilities = capabilities,
          cmd = {
            "clangd",
            "--background-index",
            "--clang-tidy",
          },
        }

        -------------------
        -- TreeSitter setup
        -------------------
        require'nvim-treesitter.configs'.setup {
          highlight = {
            enable = true,
            custom_captures = {
            -- Highlight the @foo.bar capture group with the "Identifier" highlight group.
              ["foo.bar"] = "Identifier",
            },
            -- Setting this to true will run `:h syntax` and tree-sitter at the same time.
            -- Set this to `true` if you depend on 'syntax' being enabled (like for indentation).
            -- Using this option may slow down your editor, and you may see some duplicate highlights.
            -- Instead of true it can also be a list of languages
            additional_vim_regex_highlighting = false,
          },
        }
      EOF
    '';

  };
}