local M = {}

-- telescope >>>
M.telescope = function ()
   -- telescope action binds >>>
   local map = vim.api.nvim_set_keymap
   local opt = {
      noremap = true,
      silent = true,
   }

   map("n", "<leader>sf", "<cmd>lua require('telescope.builtin').find_files()<cr>", opt)
   map("n", "<leader>sg", "<cmd>lua require('telescope.builtin').live_grep()<cr>",  opt)
   map("n", "<leader>sb", "<cmd>lua require('telescope.builtin').buffers()<cr>",    opt)
   map("n", "<leader>ss", "<cmd>lua require('telescope.builtin').lsp_dynamic_workspace_symbols()<cr>", opt)
   -- <<<

   -- telescope config >>>
   require('telescope').setup(
   )
   -- <<<
end
-- <<<

-- nvimtree >>>
M.nvimtree = function ()
   require'nvim-tree'.setup {
      hijack_cursor = true,
   }
end -- <<<

-- toggleterm >>>
M.toggleterm = function()
   require("toggleterm").setup{
      -- size can be a number or function which is passed the current terminal
      size = function(term)
         if term.direction == "horizontal" then
            return 15
         elseif term.direction == "vertical" then
            return vim.o.columns * 0.4
         end
      end,
      open_mapping = [[<F12>]],
      hide_numbers = true, -- hide the number column in toggleterm buffers
      shade_filetypes = {},
      shade_terminals = true,
      shading_factor = '1', -- the degree by which to darken to terminal colour, default: 1 for dark backgrounds, 3 for light
      start_in_insert = true,
      insert_mappings = true, -- whether or not the open mapping applies in insert mode
      persist_size = true,
      direction = 'float', -- vertical, horizontal, window, or float
      close_on_exit = true, -- close the terminal window when the process exits
      -- shell = vim.o.shell, -- change the default shell
      -- This field is only relevant if direction is set to 'float'
      float_opts = {
         -- The border key is *almost* the same as 'nvim_open_win'
         -- see :h nvim_open_win for details on borders however
         -- the 'curved' border is a custom border type
         -- not natively supported but implemented in this plugin.
         border = 'curved', -- single, double, shadow, or curved
         width = 200,
         height = 50,
         winblend = 10, -- transparancy
         highlights = {
            border = "Normal",
            background = "Normal",
         }
      }
   }
end -- <<<

-- gitsigns >>>
M.gitsigns = function()
   require('gitsigns').setup {
      signs = {
         add          = {hl = 'GitSignsAdd'   , text = '│', numhl='GitSignsAddNr'   , linehl='GitSignsAddLn'},
         change       = {hl = 'GitSignsChange', text = '│', numhl='GitSignsChangeNr', linehl='GitSignsChangeLn'},
         delete       = {hl = 'GitSignsDelete', text = '_', numhl='GitSignsDeleteNr', linehl='GitSignsDeleteLn'},
         topdelete    = {hl = 'GitSignsDelete', text = '‾', numhl='GitSignsDeleteNr', linehl='GitSignsDeleteLn'},
         changedelete = {hl = 'GitSignsChange', text = '~', numhl='GitSignsChangeNr', linehl='GitSignsChangeLn'},
      },
      signcolumn = true,  -- Toggle with `:Gitsigns toggle_signs`
      numhl      = false, -- Toggle with `:Gitsigns toggle_numhl`
      linehl     = false, -- Toggle with `:Gitsigns toggle_linehl`
      word_diff  = false, -- Toggle with `:Gitsigns toggle_word_diff`
      keymaps = {
         -- Default keymap options
         noremap = true,
         ['n ]c'] = { expr = true, "&diff ? ']c' : '<cmd>lua require\"gitsigns.actions\".next_hunk()<CR>'"},
         ['n [c'] = { expr = true, "&diff ? '[c' : '<cmd>lua require\"gitsigns.actions\".prev_hunk()<CR>'"},
         -- hunk binds
         ['n <leader>hs'] = '<cmd>lua require"gitsigns".stage_hunk()<CR>',
         ['v <leader>hs'] = '<cmd>lua require"gitsigns".stage_hunk({vim.fn.line("."), vim.fn.line("v")})<CR>',
         ['n <leader>hu'] = '<cmd>lua require"gitsigns".undo_stage_hunk()<CR>',
         ['n <leader>hr'] = '<cmd>lua require"gitsigns".reset_hunk()<CR>',
         ['v <leader>hr'] = '<cmd>lua require"gitsigns".reset_hunk({vim.fn.line("."), vim.fn.line("v")})<CR>',
         ['n <leader>hp'] = '<cmd>lua require"gitsigns".preview_hunk()<CR>',
         -- buffer binds
         ['n <leader>hS'] = '<cmd>lua require"gitsigns".stage_buffer()<CR>',
         ['n <leader>hR'] = '<cmd>lua require"gitsigns".reset_buffer()<CR>',
         ['n <leader>hU'] = '<cmd>lua require"gitsigns".reset_buffer_index()<CR>',
         -- misc.
         ['n <leader>hb'] = '<cmd>lua require"gitsigns".blame_line(true)<CR>',
         -- Text objects
         ['o ih'] = '<cmd><C-U>lua require"gitsigns.actions".select_hunk()<CR>',
         ['x ih'] = '<cmd><C-U>lua require"gitsigns.actions".select_hunk()<CR>'
      },
      watch_gitdir = {
         interval = 1000,
         follow_files = true
      },
      attach_to_untracked = true,
      current_line_blame = false, -- Toggle with `:Gitsigns toggle_current_line_blame`
      current_line_blame_opts = {
         virt_text = true,
         virt_text_pos = 'eol', -- 'eol' | 'overlay' | 'right_align'
         delay = 1000,
      },
      current_line_blame_formatter_opts = {
         relative_time = false
      },
      sign_priority = 6,
      update_debounce = 100,
      status_formatter = nil, -- Use default
      max_file_length = 40000,
      preview_config = {
         -- Options passed to nvim_open_win
         border = 'single',
         style = 'minimal',
         relative = 'cursor',
         row = 0,
         col = 1
      },
      yadm = {
         enable = false
      },
   }
end -- <<<

-- neoscroll for smooth scrolling >>>
M.neoscroll = function()
   require('neoscroll').setup({
      -- All these keys will be mapped to their corresponding default scrolling animation
      mappings = { '<C-u>', '<C-d>', '<C-b>', '<C-f>', '<C-y>', '<C-e>',
         'zt', 'zz', 'zb', '<ScrollWheelUp>', '<ScrollWheelDown>', },
      hide_cursor = true,          -- Hide cursor while scrolling
      stop_eof = true,             -- Stop at <EOF> when scrolling downwards
      use_local_scrolloff = false, -- Use the local scope of scrolloff instead of the global scope
      respect_scrolloff = false,   -- Stop scrolling when the cursor reaches the scrolloff margin of the file
      cursor_scrolls_alone = true, -- The cursor will keep on scrolling even if the window cannot scroll further
      easing_function = 'sine',    -- use sine easing function
      pre_hook = nil,              -- Function to run before the scrolling animation starts
      post_hook = nil,             -- Function to run after the scrolling animation ends
   })
end
-- <<<

-- indent_blankline >>>
M.indent_blankline = function()
   vim.cmd [[
      let g:indent_blankline_show_first_indent_level = v:true
      let g:indent_blankline_show_foldtext = v:false
      let g:indent_blankline_buftype_exclude = ['terminal']
      let g:indent_blankline_use_treesitter = v:true
      let g:indent_blankline_show_current_context = v:true
   ]]
   require("indent_blankline").setup {
      show_current_context = true,
      show_current_context_start = false,
   }
end
-- <<<

-- ZenMode >>>
M.zenmode = function()
   -- map :ZM to :ZenMode
   vim.cmd 'command! ZM ZenMode'
   require("zen-mode").setup {
      window = {
         backdrop = 1, -- shade the backdrop of the Zen window. Set to 1 to keep the same as Normal
         -- height and width can be:
         -- * an absolute number of cells when > 1
         -- * a percentage of the width / height of the editor when <= 1
         -- * a function that returns the width or the height
         width = 120, -- width of the Zen window
         height = 51-2, -- height of the Zen window
         -- by default, no options are changed for the Zen window
         -- uncomment any of the options below, or add other vim.wo options you want to apply
         options = { -- uncomment to do what the sign says
            -- signcolumn = "no",      -- signcolumn
            number = false,         -- number column
            -- relativenumber = false, -- relative numbers
            -- cursorline = false,     -- cursorline
            cursorcolumn = false,   -- cursor column
            -- foldcolumn = "0",       -- fold column
            -- list = false,           -- whitespace characters
         },
      },
      plugins = {
         -- disable some global vim options (vim.o...)
         -- comment the lines to not apply the options
         options = {
            enabled = true,
            ruler = false, -- disables the ruler text in the cmd line area
            showcmd = false, -- disables the command in the last line of the screen
         },
         twilight = { enabled = true }, -- enable to start Twilight when zen mode opens
         gitsigns = { enabled = true }, -- disables git signs
         tmux = { enabled = false }, -- disables the tmux statusline
      },
   }
end
-- <<<

-- Autosession >>>
M.autosession = function()
   local opts = {
      log_level = 'info',
      auto_session_enable_last_session = true,
      auto_session_root_dir = vim.fn.stdpath('data').."/sessions/",
      auto_session_enabled = true,
      auto_save_enabled = false,
      auto_restore_enabled = true,
      auto_session_suppress_dirs = nil,
   }
   require('auto-session').setup(opts)
   -- save some more things. notably options, resize, winpos, and terminal
   vim.o.sessionoptions="blank,buffers,curdir,folds,help,tabpages,resize,winpos,terminal"
   -- So I don't forget which one it is
   vim.cmd 'command! SessionSave    SaveSession'
   vim.cmd 'command! SessionDelete  DeleteSession'
   vim.cmd 'command! SessionRestore RestoreSession'
end -- <<<

-- Lualine >>>
M.lualine = function()
   -- From https://github.com/nvim-lualine/lualine.nvim/blob/master/examples/evil_lualine.lua
   -- Eviline config for lualine
   -- Author: shadmansaleh
   -- Credit: glepnir
   -- Example:
   -- ▊   20.2k  .zshrc  320:1    56%                                     LSP: bashls                                  UTF-8  UNIX  ▊
   local lualine = require 'lualine'

   -- Color table for highlights
   -- stylua: ignore
   -- Onedark colors
   -- local colors = {
   --    bg       = '#21242B',
   --    fg       = '#bbc2cf',
   --    yellow   = '#ECBE7B',
   --    cyan     = '#008080',
   --    darkblue = '#081633',
   --    green    = '#98be65',
   --    orange   = '#FF8800',
   --    violet   = '#a9a1e1',
   --    magenta  = '#c678dd',
   --    blue     = '#51afef',
   --    red      = '#ec5f67',
   -- }
   local colors = {
      bg       = '#1a1b26',
      fg       = '#c0caf5',
      red      = '#f7768e',
      orange   = '#ff9e64',
      yellow   = '#e0af68',
      green    = '#9ece6a',
      cyan     = '#7dcfff',
      blue     = '#7aa2f7',
      darkblue = '#081633',
      violet   = '#6d60e0',
      magenta  = '#bb9af7',
   }

   local conditions = {
      buffer_not_empty = function()
         return vim.fn.empty(vim.fn.expand '%:t') ~= 1
      end,
      hide_in_width = function()
         return vim.fn.winwidth(0) > 80
      end,
      check_git_workspace = function()
         local filepath = vim.fn.expand '%:p:h'
         local gitdir = vim.fn.finddir('.git', filepath .. ';')
         return gitdir and #gitdir > 0 and #gitdir < #filepath
      end,
   }

   -- Config
   local config = {
      options = {
         -- Disable sections and component separators
         component_separators = '',
         section_separators = '',
         theme = {
            -- We are going to use lualine_c an lualine_x as left and
            -- right section. Both are highlighted by c theme .  So we
            -- are just setting default looks o statusline
            normal = { c = { fg = colors.fg, bg = colors.bg } },
            inactive = { c = { fg = colors.fg, bg = colors.bg } },
         },
      },
      sections = {
         -- these are to remove the defaults
         lualine_a = {},
         lualine_b = {},
         lualine_y = {},
         lualine_z = {},
         -- These will be filled later
         lualine_c = {},
         lualine_x = {},
      },
      inactive_sections = {
         -- these are to remove the defaults
         lualine_a = {},
         lualine_b = {},
         lualine_y = {},
         lualine_z = {},
         lualine_c = {},
         lualine_x = {},
      },
   }

   -- Inserts a component in lualine_c at left section
   local function ins_left(component)
      table.insert(config.sections.lualine_c, component)
   end

   -- Inserts a component in lualine_x ot right section
   local function ins_right(component)
      table.insert(config.sections.lualine_x, component)
   end

   ins_left {
      function()
         return '▊'
      end,
      color = { fg = colors.blue }, -- Sets highlighting of component
      padding = { left = 0, right = 1 }, -- We don't need space before this
   }

   ins_left {
      -- mode component
      function()
         -- auto change color according to neovims mode
         local mode_color = {
            n = colors.green,
            i = colors.blue,
            v = colors.magenta,
            [''] = colors.magenta,
            V = colors.magenta,
            c = colors.violet,
            no = colors.green,
            s = colors.orange,
            S = colors.orange,
            [''] = colors.orange,
            ic = colors.yellow,
            R = colors.red,
            Rv = colors.red,
            cv = colors.green,
            ce = colors.green,
            r = colors.cyan,
            rm = colors.cyan,
            ['r?'] = colors.cyan,
            ['!'] = colors.green,
            t = colors.green,
         }
         vim.api.nvim_command('hi! LualineMode guifg=' .. mode_color[vim.fn.mode()] .. ' guibg=' .. colors.bg)
         return ''
      end,
      color = 'LualineMode',
      padding = { right = 1 },
   }

   ins_left {
      -- filesize component
      'filesize',
      cond = conditions.buffer_not_empty,
   }

   ins_left {
      'filename',
      cond = conditions.buffer_not_empty,
      color = { fg = colors.magenta, gui = 'bold' },
   }

   ins_left { 'location' }

   ins_left { 'progress', color = { fg = colors.fg, gui = 'bold' } }

   ins_left {
      'diagnostics',
      sources = { 'nvim_diagnostic' },
      symbols = { error = ' ', warn = ' ', info = ' ' },
      diagnostics_color = {
         color_error = { fg = colors.red },
         color_warn = { fg = colors.yellow },
         color_info = { fg = colors.cyan },
      },
   }

   -- Insert mid section. You can make any number of sections in neovim :)
   -- for lualine it's any number greater then 2
   ins_left {
      function()
         return '%='
      end,
   }

   -- ins_left {
   --    -- Lsp server name .
   --    function()
   --       local msg = 'No Active Lsp'
   --       local buf_ft = vim.api.nvim_buf_get_option(0, 'filetype')
   --       local clients = vim.lsp.get_active_clients()
   --       if next(clients) == nil then
   --          return msg
   --       end
   --       for _, client in ipairs(clients) do
   --          local filetypes = client.config.filetypes
   --          if filetypes and vim.fn.index(filetypes, buf_ft) ~= -1 then
   --             return client.name
   --          end
   --       end
   --       return msg
   --    end,
   --    icon = ' LSP:',
   --    color = { fg = '#ffffff', gui = 'bold' },
   -- }

   -- Add components to right sections
   ins_right {
      'o:encoding', -- option component same as &encoding in viml
      fmt = string.upper, -- I'm not sure why it's upper case either ;)
      cond = conditions.hide_in_width,
      color = { fg = colors.green, gui = 'bold' },
   }

   ins_right {
      'fileformat',
      fmt = string.upper,
      icons_enabled = false, -- I think icons are cool but Eviline doesn't have them. sigh
      color = { fg = colors.green, gui = 'bold' },
   }

   ins_right {
      'branch',
      icon = '',
      color = { fg = colors.violet, gui = 'bold' },
   }

   ins_right {
      'diff',
      -- Is it me or the symbol for modified us really weird
      symbols = { added = ' ', modified = '柳 ', removed = ' ' },
      diff_color = {
         added = { fg = colors.green },
         modified = { fg = colors.orange },
         removed = { fg = colors.red },
      },
      cond = conditions.hide_in_width,
   }

   ins_right {
      function()
         return '▊'
      end,
      color = { fg = colors.blue },
      padding = { left = 1 },
   }

   -- Now don't forget to initialize lualine
   lualine.setup(config)
end -- <<<

return M

-- vim:fdm=marker:fmr=>>>,<<<:expandtab:tabstop=3:sw=3