local fn,api = vim.fn,vim.api
local packer_dir = fn.stdpath('data') .. '/site/pack/packer/opt/packer.nvim'

if fn.empty(fn.glob(packer_dir)) > 0 then
    fn.system({'git', 'clone', 'https://github.com/wbthomason/packer.nvim', packer_dir})
    api.nvim_command('packadd packer.nvim')
end

-- Require since we use 'packer' as opt
vim.cmd [[packadd packer.nvim]]

return require('packer').startup(
    function(use)
        use {'wbthomason/packer.nvim', opt = true}

        -----------------
        -- UI elements --
        -----------------
        use {
            'glepnir/dashboard-nvim',
            cmd = {
                'Dashboard',
                'DashboardNewFile',
                'DashboardFindFile',
                'DashboardFindHistory',
                'DashboardFindWord',
                'DashboardJumpMark',
                'SessionLoad',
                'SessionSave'
            },
            setup = function()
                require('modules.dashboard')
            end
        }
        use {
            'glepnir/galaxyline.nvim',
            branch = 'main',
            requires = 'kyazdani42/nvim-web-devicons',
            config = function()
                require('modules.statusline')
            end
        }
        use {
            'akinsho/nvim-bufferline.lua',
            config = function()
                require('modules.bufferline')
            end
        }
        use {
            'kyazdani42/nvim-tree.lua',
            cmd = 'NvimTreeToggle',
            setup = function()
                require('modules.nvimtree')
            end
        }
        use {
            'folke/which-key.nvim',
            config = function()
                require('modules.whichkey')
            end
        }

        ------------------
        -- Highlighting --
        ------------------
        use {
            'lewis6991/gitsigns.nvim',
            event = {'BufRead', 'BufNewFile'},
            wants = 'plenary.nvim',
            requires = {{'nvim-lua/plenary.nvim', opt = true}},
            config = function()
                require('modules.gitgutter')
            end
        }
        use {
            'norcalli/nvim-colorizer.lua',
            cmd = 'ColorizerToggle',
            config = function()
                require('modules.colorizer')
            end
        }
        use {
            'RRethy/vim-illuminate',
            event = {'BufRead', 'BufNewFile'}
        }
        use {
            'lukas-reineke/indent-blankline.nvim',
            event = 'BufRead',
            config = function()
                require('modules.blankline')
            end
        }
        use {
            'nvim-treesitter/nvim-treesitter',
            run = ':TSUpdate',
            event = 'BufRead',
            config = function()
                require('modules.treesitter')
            end
        }
        use {
            'p00f/nvim-ts-rainbow',
            after = 'nvim-treesitter',
            config = function()
                require('nvim-treesitter.configs').setup {
                    rainbow = {
                        enable = true,
                        extended_mode = false,
                        max_file_lines = 1000
                    }
                }
            end
        }
        use {
            'romgrk/nvim-treesitter-context',
            after = 'nvim-treesitter'
        }

        ---------
        -- LSP --
        ---------
        use {
            'neovim/nvim-lspconfig',
            event = 'BufReadPre',
            config = function()
                require('modules.lsp')
            end
        }
        use {
            'onsails/lspkind-nvim',
            event = 'InsertEnter',
            config = function()
                require('lspkind').init({with_text = false})
            end
        }
        use {
            'folke/trouble.nvim',
            event = 'BufRead',
            config = function()
                require('modules.lsptrouble')
            end
        }
        use {
            'simrat39/symbols-outline.nvim',
            cmd = {'SymbolsOutline', 'SymbolsOutlineOpen'},
            setup = function()
                vim.g.symbols_outline = {
                    highlight_hovered_item = false,
                    show_guides = false
                }
            end
        }
        use {
            'hrsh7th/nvim-compe',
            event = 'InsertEnter',
            config = function()
                require('modules.completion')
            end
        }
        use {
            'L3MON4D3/LuaSnip', -- can't lazy-load (conflicts with autopairs' map_cr)
            requires = 'rafamadriz/friendly-snippets',
            config = function()
                require('modules.snippets')
            end
        }

        ---------------
        -- Utilities --
        ---------------
        use {
            'nvim-telescope/telescope.nvim',
            cmd = 'Telescope',
            wants = {
                'popup.nvim',
                'plenary.nvim',
                'telescope-symbols.nvim',
                'telescope-project.nvim',
                'telescope-fzf-native.nvim'
            },
            requires = {
                {'nvim-lua/popup.nvim', opt = true},
                {'nvim-lua/plenary.nvim', opt = true},
                {'nvim-telescope/telescope-symbols.nvim', opt = true},
                {'nvim-telescope/telescope-project.nvim', opt = true},
                {'nvim-telescope/telescope-fzf-native.nvim', run = 'make', opt = true}
            },
            config = function()
                require('modules.telescope-nvim')
            end
        }
        use { -- TODO: colors + config
            'pwntester/octo.nvim',
            cmd = 'Octo',
            wants = 'telescope.nvim',
            config = function()
                require('octo').setup()
            end
        }
        use {
            'TimUntersberger/neogit',
            cmd = 'Neogit',
            wants = {
                'diffview.nvim',
                'plenary.nvim'
            },
            requires = {
                {'nvim-lua/plenary.nvim', opt = true},
                {
                    'sindrets/diffview.nvim',
                    config = function()
                        require('diffview').setup {
                            diff_binaries = true
                        }
                    end,
                    opt = true
                }
            },
            config = function()
                require('neogit').setup {
                    integrations = {
                        diffview = true
                    }
                }
            end
        }
        use {
            'kristijanhusak/vim-dadbod-ui',
            cmd = {'DBUIToggle', 'DBUIAddConnection', 'DBUI', 'DBUIFindBuffer', 'DBUIRenameBuffer'},
            wants = 'vim-dadbod',
            requires = {{'tpope/vim-dadbod', opt = true}},
            config = function()
                require('modules.dadbod')
            end
        }
        use {
            'kristijanhusak/vim-dadbod-completion',
            after = 'vim-dadbod-ui',
            config = function()
                vim.g.compe.source.vim_dadbod_completion = true
            end
        }
        use {
            'windwp/nvim-autopairs',
            event = 'InsertCharPre',
            config = function()
                require('nvim-autopairs').setup()
                require('nvim-autopairs.completion.compe').setup({
                    map_cr = true,
                    map_complete = true
                })
            end
        }
        use {
            'machakann/vim-sandwich',
            keys = {'sa', 'sd', 'sr'}
        }
        use {
            'phaazon/hop.nvim',
            cmd = {'HopChar1', 'HopChar2', 'HopWord', 'HopPattern', 'HopLine'},
            config = function()
                require('hop').setup{keys = 'etovxqpdygfblzhckisuran'}
            end
        }
        use {
            'junegunn/vim-easy-align',
            keys = 'ga'
        }
        use {
            'terrortylor/nvim-comment',
            keys = 'gc',
            config = function()
                require('nvim_comment').setup({comment_empty = false})
            end
        }
        use {
            'windwp/nvim-ts-autotag',
            ft = {
                'html',
                'xml',
                'javascript',
                'javascriptreact',
                'typescript',
                'typescriptreact',
                'vue',
                'svelte',
                'php'
            },
            wants = 'nvim-treesitter',
            config = function()
                require('nvim-treesitter.configs').setup {
                    autotag = {
                        enable = true
                    }
                }
            end
        }
        use {
            'ahmedkhalf/lsp-rooter.nvim',
            after = 'nvim-lspconfig'
        }
        use {
            'iamcco/markdown-preview.nvim',
            run = 'cd app && yarn install',
            ft = {'markdown', 'pandoc.markdown', 'rmd'},
            config = function()
                require('modules.markdown-preview')
            end
        }
        use {
            'turbio/bracey.vim',
            run = 'npm install --prefix server',
            cmd = 'Bracey'
        }
        use {
            'folke/zen-mode.nvim',
            cmd = 'ZenMode',
            wants = 'twilight.nvim',
            requires = {{'folke/twilight.nvim', opt = true}},
            config = function()
                require('modules.zen')
            end
        }
        use {
            'kristijanhusak/orgmode.nvim', -- shouldn't be lazy-loaded (otherwise bindings don't work)
            ft = 'org',
            config = function()
                require('modules.org')
            end
        }
        use {
            'echuraev/translate-shell.vim',
            cmd = {'Trans', 'TransSelectDirection'},
            config = function()
                require('modules.translate-shell')
            end
        }
        use {
            'akinsho/nvim-toggleterm.lua',
            cmd = 'ToggleTerm',
            config = function()
                require('modules.terminal')
            end
        }
        -- Just for benchmarking
        use {'tweekmonster/startuptime.vim', cmd = 'StartupTime'}
        -- File picker, since Telescope file browser doesn't support dotfiles
        use {
            'mcchrish/nnn.vim',
            cmd = 'NnnPicker',
            config = function()
               require('modules.picker')
            end
        }

        -- TODO: lspsaga, nvim-lint, format(ter).nvim, rest.nvim, sqls.nvim,
        -- nvim-spectre, nvim-dap, dial.nvim, asynctasks.nvim
    end
)
