set nocompatible
set backspace=start,eol,indent
set hidden
set hlsearch
syntax on
filetype plugin on
set tabstop=4 shiftwidth=4 autoindent smartindent expandtab
set mouse=v

if !has('nvim')
  set ttymouse=xterm2
endif

if has('nvim')
  tnoremap <Esc> <C-\><C-n>
  set mouse+=a
endif

let mapleader=","

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
"
" Numbering of lines
"
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" set relativenumber
set number

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
"
" Runtimepath variables
"
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" call -> set rtp? show the runtime path
let $RTP=split(&runtimepath, ',')[0]
let $RC="$HOME/.vimrc"

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
"
" Move Swap,Backup and undo files into .vim directory
"
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
set directory^=$HOME/.vim/.swap//
set backupdir^=$HOME/.vim/.backup//
set undodir^=$HOME/.vim/.undo//

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
"
" Split to the right and below
"
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
set splitbelow
set splitright

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
"
" Folding
"
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
set foldenable foldlevelstart=20 foldmethod=indent

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
"
" Rebind shortcut to switch splits
"
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
nmap <C-h> <C-w>h
nmap <C-j> <C-w>j
nmap <C-k> <C-w>k
nmap <C-l> <C-w>l

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
"
" Finding files
"
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
set path+=**
set wildmenu
set wildmode=longest:full,full

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
"
" Create Tags thorugh :MakeTags
"
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
command! MakeTags !ctags -R .
set autochdir
set tags=tags;

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
"
" File browsing through a tree on the left side
"
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
let g:netrw_banner=0
let g:netrw_browse_split=4
let g:netrw_altv=1
let g:netrw_liststyle=3
" let g:netrw_list_hide=netrw_gitignore#Hide()
" let g:netrw_list_hide=',\(\^\|\s\s\)\zs\.\S\+'
let g:netrw_list_hide='\(^|\s\s\)\zs\.\S\+'
map <C-n>  :Lex <bar> vertical resize 30 <CR>

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
"
" Cursorline on the cursor
"
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
set cursorline
hi CursorLine  cterm=NONE ctermbg=darkgrey ctermfg=white

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
"
" gitgutter configurations
"
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

nmap ]h <Plug>(GitGutterNextHunk)
nmap [h <Plug>(GitGutterPrevHunk)

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
"
" Colors
"
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
set termguicolors
" set t_Co=256
" colorscheme gruvbox
colorscheme catppuccin_macchiato
set bg=dark

" tmux color correction

if exists('+termguicolors')
  let &t_8f = "\<Esc>[38;2;%lu;%lu;%lum"
  let &t_8b = "\<Esc>[48;2;%lu;%lu;%lum"
  set termguicolors
endif

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
"
" Status Line on the bottom
"
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Statusline
" function! gitbranch()
"   return system("git rev-parse --abbrev-ref head 2>/dev/null | tr -d '\n'")
" endfunction
"
" function! statuslinegit()
"   let l:branchname = gitbranch()
"   return strlen(l:branchname) > 0?'  '.l:branchname.' ':''
" endfunction
function! UpdateGitBranch()
  let l:branchname = system("git rev-parse --abbrev-ref HEAD 2>/dev/null | tr -d '\n'")
  let b:branchstatus = strlen(l:branchname) > 0? '  '.l:branchname.' ':''
endfunction

augroup UPDATE_GITBRANCH
" clear previous commands
autocmd!
" Update git branch
autocmd BufWritePre * :call UpdateGitBranch()
autocmd BufReadPost * :call UpdateGitBranch()
autocmd BufEnter *    :call UpdateGitBranch()
augroup end

function! LinterStatus() abort
    let l:counts = ale#statusline#Count(bufnr(''))

    let l:all_errors = l:counts.error + l:counts.style_error
    let l:all_non_errors = l:counts.total - l:all_errors

    return l:counts.total == 0 ? 'OK' : printf(
    \   'Lint: %dW %dE',
    \   all_non_errors,
    \   all_errors
    \)
endfunction

" gitgutter: get a list of counts of added, modified, and removed lines in the current buffer
function! GitStatus()
  let [a,m,r] = GitGutterGetHunkSummary()
  return printf('ap:+%d md: ~%d rm: -%d', a, m, r)
endfunction

highlight BufTab ctermfg=black ctermbg=White
highlight GitDetails ctermfg=Magenta ctermbg=Black
highlight FileDetails ctermfg=Black ctermbg=Blue

set laststatus=2
set statusline=
set statusline+=%#PmenuSel#
" set statusline+=%{StatuslineGit()}
set statusline+=%{b:branchstatus}
set statusline+=%#BufTab#
set statusline+=\ %M
set statusline+=\ %r
set statusline+=\ %F
set statusline+=%= "Right side settings
" set statusline+=%{FugitiveStatusline()}
set statusline+=%#GitDetails#
set statusline+=[%{GitStatus()}]
set statusline+=\ [%{LinterStatus()}\]
set statusline+=\ %y
set statusline+=%#FileDetails#
set statusline+=\ %{&fileencoding?&fileencoding:&encoding}
set statusline+=\[%{&fileformat}\]
set statusline+=\ [%c:%l/%L]
set statusline+=\ %p%%
set statusline+=\ [%n]

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
"
" tagbar, press F8
"
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
nmap <F8> :TagbarToggle<CR>

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
"
" Selection Highlighting
"
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" hlsearch colors
highlight Search ctermbg=black ctermfg=darkgrey ctermbg=grey
" Highlight all instances of word under cursor, when idle.
function! AutoHighlightToggle()
  let @/ = ''
    augroup auto_highlight
      au!
      au CursorHold * let @/ = '\V\<'.escape(expand('<cword>'), '\').'\>'
    augroup end
    setl updatetime=1600
endfunction
call AutoHighlightToggle()

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
"
" Code Completion
"
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
set lazyredraw
set splitright
let g:ale_enabled = 1
let g:ale_hover_enabled = 1
let g:ale_set_balloons = 1
let g:ale_sign_error = '✗'
" let g:ale_sign_warning = ''
let g:ale_completion_enabled = 1
let g:ale_completion_autoimport = 1
" let g:ale_floating_window_border = ['│', '─', '╭', '╮', '╯', '╰', '│', '─']
" let g:ale_floating_window_border = repeat([''], 8)
let g:ale_close_preview_on_insert = 1
let g:ale_hover_to_preview = 1
let g:ale_use_neovim_lsp_api = 0

let g:ale_echo_msg_error_str = 'E'
let g:ale_echo_msg_warning_str = 'W'
let g:ale_echo_msg_format = '[%linter%], [%severity%] %s' " let g:ale_popup_menu_enabled = 1
nmap gr :ALEFindReferences<CR>
nmap T :ALEHover<CR>
" nmap gd :ALEGoToDefinition<CR>

" set completeopt+=menuone
" set completeopt+=noselect
" set completeopt+=noinsert
set shortmess+=c   " Shut off completion messages
set belloff+=ctrlg " Add only if Vim beeps during completion
let g:mucomplete#enable_auto_at_startup = 1
let g:mucomplete#completion_delay = 0

" set omnifunc=syntaxcomplete#Complete
" set omnifunc=ale#completion#Complete
" set omnifunc=ale#completion#OmniFunc
"let g:ale_completion_enabled=1
"function! OpenCompletion()
"    if !pumvisible() && ((v:char >= 'a' && v:char <= 'z') || (v:char >= 'A' && v:char <= 'Z'))
"        call feedkeys("\<C-x>\<C-o>", "n")
"    endif
"endfunction
"
"autocmd InsertCharPre * call OpenCompletion()
"
set completeopt+=longest,menu,menuone,preview,noselect,noinsert
set splitkeep=screen
"" set completeopt+=menuone,noselect,noinsert
""
" autocmd InsertLeave,CompleteDone * if pumvisible() == 0 | pclose | endif

"
"
" --This puts the preview window to the right of the screen
"
" augroup previewWindowPosition
"    au!
"    autocmd BufWinEnter * call PreviewWindowPosition()
" augroup END
" function! PreviewWindowPosition()
"    if &previewwindow
"       wincmd L
"    endif
" endfunction

let g:ale_fixers = {
\   '*': ['remove_trailing_lines', 'trim_whitespace'],
\}

let g:ale_fix_on_save = 1
let g:ale_disable_lsp = 'auto'

" Go to previous and next warning and error via ALE
nmap <silent> <C-k> <Plug>(ale_previous_wrap)
nmap <silent> <C-j> <Plug>(ale_next_wrap)

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
"
" undotree
"
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
nnoremap <F5> :UndotreeToggle<CR>

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
"
" Remove conceal from Markdown when Insert mode is set
"
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
autocmd InsertEnter  *.{markdown,md} set conceallevel=0
autocmd InsertLeave  *.{markdown,md} set conceallevel=2

autocmd InsertEnter  *.{json} set conceallevel=0
autocmd InsertLeave  *.{json} set conceallevel=2

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
"
" Load all packages and activate tags
"
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" packadd! vim-polyglot
" packadd! vim-log-highlighting
" packloadall
" Load all of the helptags now, after plugins have been loaded.
" All messages and errors will be ignored.
silent! helptags ALL
silent! helptags ALE
silent! helptags vim-gitgutter/doc

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
"
" FZF Integration
"
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

set rtp+=$HOME/.fzf
nnoremap <silent> <Leader>b :Buffers<CR>
nnoremap <silent> <C-f> :Files<CR>
nnoremap <silent> <Leader>r :Files ~<CR>
nnoremap <silent> <Leader>f :Rg<CR>
nnoremap <silent> <Leader>/ :BLines<CR>
nnoremap <silent> <Leader>' :Marks<CR>
nnoremap <silent> <Leader>g :Commits<CR>
nnoremap <silent> <Leader>H :Helptags<CR>
nnoremap <silent> <Leader>hh :History<CR>
nnoremap <silent> <Leader>h: :History:<CR>
nnoremap <silent> <Leader>h/ :History/<CR>

" Customize fzf colors to match your color scheme
" - fzf#wrap translates this to a set of `--color` options
let g:fzf_colors =
\ { 'fg':      ['fg', 'Normal'],
  \ 'bg':      ['bg', 'Normal'],
  \ 'hl':      ['fg', 'Comment'],
  \ 'fg+':     ['fg', 'CursorLine', 'CursorColumn', 'Normal'],
  \ 'bg+':     ['bg', 'CursorLine', 'CursorColumn'],
  \ 'hl+':     ['fg', 'Statement'],
  \ 'info':    ['fg', 'PreProc'],
  \ 'border':  ['fg', 'Ignore'],
  \ 'prompt':  ['fg', 'Conditional'],
  \ 'pointer': ['fg', 'Exception'],
  \ 'marker':  ['fg', 'Keyword'],
  \ 'spinner': ['fg', 'Label'],
  \ 'header':  ['fg', 'Comment'] }

function! FzfSearchUpwards()
  let l:dir = getcwd()
  while !isdirectory(l:dir . "/.git") && l:dir != "/"
    let l:dir = fnamemodify(l:dir, ":h")
  endwhile
  execute "Files " . l:dir
endfunction

nnoremap <leader>fu :call FzfSearchUpwards()<CR>

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
"
" Functions to base64 encode/decode the exact selected text and replace it
" without a newline
"
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

" xnoremap <leader>c <esc>=:'<,'>:w ! base64<C-M>p

function! Base64EncodeSelection()
  normal! gv"vy
  let l:selected_text = getreg('"')
  let l:encoded_text = system('echo -n ' . shellescape(l:selected_text) . ' | base64 -w0')
  let l:encoded_text = trim(l:encoded_text)
  execute "normal! gv\"_c" . l:encoded_text
endfunction
xnoremap <leader>be :<C-u>call Base64EncodeSelection()<CR>

function! Base64DecodeSelection()
  normal! gv"vy
  let l:selected_text = getreg('"')
  let l:encoded_text = system('echo -n ' . shellescape(l:selected_text) . ' | base64 -d')
  let l:encoded_text = trim(l:encoded_text)
  execute "normal! gv\"_c" . l:encoded_text
endfunction
xnoremap <leader>bd :<C-u>call Base64DecodeSelection()<CR>
