-- add extra filetypes for plenary
require('plenary.filetype').add_table({
  extension = {
    ['elv'] = [[elvish]]
  }
})

-- file/buffer/etc picker
require('telescope').setup({
  defaults = {
    mappings = {
      i = {
        ['jj'] = 'close',
      },
    },
    layout_config = {
      prompt_position = 'top',
    },
    sorting_strategy = 'ascending',
    -- use filename as preview window title
    dynamic_preview_title = true,

    preview = {
      -- don't preview files larger than 1MB
      filesize_limit = 1,
      timeout = 500,
    },

    -- ignore things we're likely not to edit
    file_ignore_patterns = {
      "%.zip$",
      "%.yarn/releases/",
      "%.yarn/plugins/"
    },
  },
  pickers = {
    buffers = {
      sort_lastused = true,
      sort_mru = true,
      mappings = {
        i = {
          ['<C-k>'] = 'delete_buffer'
        },
      },
    },
    find_files = {
      find_command = { "fd", "--type", "f", "--strip-cwd-prefix" }
    },
  },
})

-- use native sorter for better performance
require('telescope').load_extension('fzf')

-- custom picker to fallback to files if no git
local telescope_builtin = require('telescope.builtin')
_G.project_files = function()
  local ok = pcall(telescope_builtin.git_files, { show_untracked = true })
  if not ok then telescope_builtin.find_files({}) end
end

-- shows added/removed/changed lines
require('gitsigns').setup()

require('mini.statusline').setup({
  content = {
    -- copy-pasted from default, we just want to remove the icon
    active = function()
      local mode, mode_hl = MiniStatusline.section_mode({ trunc_width = 120 })
      local git           = MiniStatusline.section_git({ trunc_width = 75, icon = '' })
      local diagnostics   = MiniStatusline.section_diagnostics({ trunc_width = 75, icon = '' })
      local filename      = MiniStatusline.section_filename({ trunc_width = 140 })
      local fileinfo      = MiniStatusline.section_fileinfo({ trunc_width = 120 })
      local location      = MiniStatusline.section_location({ trunc_width = 75 })

      return MiniStatusline.combine_groups({
        { hl = mode_hl,                  strings = { mode } },
        { hl = 'MiniStatuslineDevinfo',  strings = { git, diagnostics } },
        '%<', -- Mark general truncate point
        { hl = 'MiniStatuslineFilename', strings = { filename } },
        '%=', -- End left alignment
        { hl = 'MiniStatuslineFileinfo', strings = { fileinfo } },
        { hl = mode_hl,                  strings = { location } },
      })
    end
  },
})

-- delete buffer while preserving layout
require('mini.bufremove').setup()

-- shows a line indicating the current indentation scope
require('mini.indentscope').setup()

-- comment actions
require('mini.comment').setup()

-- surround actions
require('mini.surround').setup()

local spec_treesitter = require('mini.ai').gen_spec.treesitter

require('mini.ai').setup({
  custom_textobjects = {
    [','] = spec_treesitter({
      a = '@parameter.outer',
      i = '@parameter.inner',
    }),
  },
});

-- align actions
require('mini.align').setup()

-- repeatable f/t
require('mini.jump').setup({
  mappings = {
    repeat_jump = '',
  },
  delay = {
    highlight = 10000000,
  },
})

-- rest client
require('rest-nvim').setup({})

-- Use Treesitter for syntax highlighting
require('nvim-treesitter.configs').setup({
  highlight = {
    enable = true,
  },
  incremental_selection = {
    enable = true,
    keymaps = {
      init_selection = "]t",
      node_incremental = "]t",
      node_decremental = "[t",
    },
  },
  textobjects = {
    swap = {
      enable = true,
      swap_next = {
        ['>,'] = '@parameter.inner',
      },
      swap_previous = {
        ['<,'] = '@parameter.inner',
      },
    },
  },
})

local tsj_utils = require('treesj.langs.utils')

-- Treesitter-aware split/join
require('treesj').setup({
  use_default_keymaps = false,

  langs = {
    nix = {
      list_expression = tsj_utils.set_preset_for_list({
        both = {
          separator = '',
        },
      }),
      binding_set = tsj_utils.set_preset_for_non_bracket(),
      let_expression = {
        target_nodes = { 'binding_set' },
      },
      attrset_expression = {
        target_nodes = { 'binding_set' },
      },

      -- this is a bit janky with the indentation
      inherited_attrs = tsj_utils.set_preset_for_non_bracket(),
      inherit = {
        target_nodes = { 'inherited_attrs' },
      },
    },
  },
})

-- completion
local cmp = require('cmp')
cmp.setup({
  snippet = {
    expand = function(args)
      vim.fn['vsnip#anonymous'](args.body)
    end,
  },
  mapping = cmp.mapping.preset.insert({
    ['<C-b>'] = cmp.mapping.scroll_docs(-4),
    ['<C-f>'] = cmp.mapping.scroll_docs(4),
    ['<C-Space>'] = cmp.mapping.complete(),
    ['<C-e>'] = cmp.mapping.abort(),
    ['<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" },
  }),
  completion = {
    autocomplete = false,
  },
})

-- typescript-vim compiler options
vim.g.typescript_compiler_options = '--incremental --noEmit'