" Install Plugged ##################################################################################

if empty(glob('~/.vim/autoload/plug.vim'))
  silent !curl -fLo ~/.vim/autoload/plug.vim --create-dirs
    \ https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
  autocmd VimEnter * PlugInstall --sync | source ~/.vimrc
endif

" Install Plugins ##################################################################################

call plug#begin('~/.vim/plugged')

" Functionality Plugins
Plug 'ctrlpvim/ctrlp.vim'
Plug 'flazz/vim-colorschemes'
Plug 'godlygeek/tabular'
Plug 'jlanzarotta/bufexplorer'
Plug 'nathanaelkane/vim-indent-guides'
Plug 'rickhowe/wrapwidth'
Plug 'scrooloose/nerdtree'
Plug 'tpope/vim-fugitive'
Plug 'vim-airline/vim-airline'
Plug 'vim-scripts/auto_autoread.vim'
Plug 'w0rp/ale'

" Language Support Plugins
"Plug 'davidhalter/jedi-vim'              " python
Plug 'digitaltoad/vim-pug'               " pug
Plug 'elzr/vim-json'                     " json
Plug 'gisraptor/vim-lilypond-integrator' " lilypond
Plug 'google/yapf'                       " python
Plug 'kchmck/vim-coffee-script'          " coffeescript
Plug 'leafgarland/typescript-vim'        " typescript
Plug 'ljfa-ag/minetweaker-highlighting'  " zenscript
Plug 'maxmellon/vim-jsx-pretty'          " jsx
Plug 'pangloss/vim-javascript'           " javascript
Plug 'hughbien/md-vim'                   " markdown
Plug 'posva/vim-vue'                     " vue
Plug 'slim-template/vim-slim'            " slim
Plug 'statianzo/vim-jade'                " jade
Plug 'stephpy/vim-yaml'                  " yaml
Plug 'vim-scripts/mako.vim'              " mako

call plug#end()

" Execute Basic Setup Commands #####################################################################

set background=dark
silent! colorscheme gruvbox

filetype plugin indent on
hi ColorColumn ctermbg=8
syntax on

" Configure Settings ###############################################################################

set autoindent
set autowrite
set autowriteall
set backspace=indent,eol,start
set cmdheight=2
set colorcolumn=100
set cursorline
set diffopt=filler,vertical
set expandtab
set exrc
set incsearch
set laststatus=2
set linebreak
set list
set listchars=tab:>-
set modelines=2
set nobackup
set nofoldenable
set nohlsearch
set noswapfile
set nowrap
set nowritebackup
set number
set path=**
set ruler
set scrolloff=5
set secure
set shell=/bin/bash\ --login
set shiftwidth=4
set showbreak=
set showcmd
set showmatch
set signcolumn=yes
set smarttab
set statusline=%<%f\ %h%m%r%*%=%-14.(%l,%c%V%)\ %P
set tabstop=4
set textwidth=100
set virtualedit=block
set visualbell
set wildignore+=node_modules,log,build,dist
set wildmode=longest,list

if executable('ag')
    set grepprg=ag\ --vimgrep\ -p\ .agignore
    set grepformat=%f:%l:%c:%m
endif

autocmd BufWritePre * %s/\s\+$//e

" Configure Plugins ################################################################################

let g:is_bash = 1

" ctrlpvim/ctrlp.vim
let g:ctrlp_working_path_mode = 0
let g:ctrlp_regexp = 0
if executable('ag')
    let g:ctrlp_user_command = 'ag %s -l --nocolor -g ""'
    let g:ctrlp_use_caching = 0
endif

" elzr/vim-json
let g:vim_json_syntax_conceal = 0

" godlygeek/tabular
nnoremap == :'a,.Tab /=/<CR>
nnoremap =: :'a,.Tab /:/<CR>
nnoremap =or :'a,.Tab /or/<CR>
nnoremap =, :'a,.Tab /,/<CR>
nnoremap =as :'a,.Tab /as/<CR>
nnoremap =import :'a,.Tab /import/<CR>

" nathanaelkane/vim-indent-guides
let g:indent_guides_enable_on_vim_startup = 0

 "plasticboy/vim-markdown
let g:vim_markdown_conceal = 0
let g:vim_markdown_conceal_code_blocks = 0

" posva/vim-vue
let g:vue_pre_processors = 'detect_on_enter'

" scrooloose/nerdtree
let g:NERDTreeIgnore = ['__pycache__', '\.pyc$', 'node_modules']

" vim-airline/vim-airline
let g:airline#extensions#ale#enabled = 1

" w0rp/ale
let g:ale_completion_delay = 500
let g:ale_completion_enabled = 1
let g:ale_echo_cursor = 1
let g:ale_echo_msg_detail = 2
let g:ale_echo_msg_format = '%linter%|%severity%: %s'
let g:ale_maximum_message_length = 200
let g:ale_fix_on_save = 1
let g:ale_hover_cursor = 1
let g:ale_lint_on_text_changed = 'always'
let g:ale_open_list = 1
let g:ale_set_loclist = 0
let g:ale_sign_column_always = 1
let g:ale_virtualenv_dir_names = ['.venv']

let g:ale_fixers = {
    \'*': ['remove_trailing_lines', 'trim_whitespace'],
    \'go': ['gofmt', 'goimports'],
    \'javascript': ['eslint'],
    \'python': [],
    \'scss': ['stylelint'],
    \'typescript': ['eslint'],
    \'typescriptreact': ['eslint']
    \}

let g:ale_linters = {
    \'go': ['gobuild', 'golint', 'govet'],
    \'html': [],
    \'javascript': ['eslint'],
    \'json': ['jsonlint'],
    \'pug': ['puglint'],
    \'python': ['pyright', 'mypy'],
    \'typescript': ['eslint', 'tsserver'],
    \'typescriptreact': ['eslint', 'tsserver'],
    \'vue': ['vls']
    \}

let g:ale_python_mypy_options =
    \ '--python-version 3.13 ' .
    \ '--check-untyped-defs ' .
    \ '--show-error-codes '


" Functions ########################################################################################

function! InsertDivider()
  " Use filetype's commentstring or default to '# %s'
  let cs = &commentstring !=# '' ? &commentstring : '# %s'

  " Extract leader (up to %s) and trim trailing spaces
  let leader = substitute(cs, '%s.*', '', '')
  let leader = substitute(leader, '\s*$', '', '')

  " Determine fill character (last non-space char of leader)
  let fillchar = matchstr(leader, '.$')

  " Determine total width (use textwidth or fallback to 80)
  let width = (&textwidth > 0 ? &textwidth : 80)

  " Capture indentation and its column width
  let indent = matchstr(getline('.'), '^\s*')
  let indentwidth = len(indent)

  " If indented, leave 20 characters to spare
  let effective_width = indentwidth > 0 ? width - 20 : width
  if effective_width < (len(leader) + 1)
    let effective_width = len(leader) + 1
  endif

  " Construct full divider line
  let line = indent . repeat(fillchar, effective_width - indentwidth)

  " Insert the line below current one
  call append('.', line)

  " Move to the inserted line, after the leader
  normal! j0
  call cursor(line('.'), len(indent) + len(leader) + 1)
endfunction

function! StartDailyReview()
  let today = strftime('%d')
  let yesterday = strftime('%d', localtime() - 86400)

  if today == '01'
      throw 'You need to perform a monthly review today.'
  endif

  let todayLog = fnameescape($'log/{today}-daily.md')
  let yesterdayLog = fnameescape($'log/{yesterday}-daily.md')

  NERDTreeClose
  execute $'edit {yesterdayLog}'
  vsplit
  set nowrap
  wincmd n
  edit log/future.md
  set nowrap
  wincmd l
  vertical resize 107
  execute $'edit {todayLog}'
  :0r templates/daily.md
endfunction

function! CopyTriggerFiles()
  let day = strftime('%d')
  let month = strftime('%m')
  let year = strftime('%Y')
  let dayName = tolower(strftime('%A'))

  let triggerFiles = [
    \ $'triggers/once/{year}/{month}/{day}-trigger.md',
    \ $'triggers/weekly/{dayName}-trigger.md',
    \ $'triggers/monthly/{day}-trigger.md',
    \ $'triggers/yearly/{month}/{day}-trigger.md',
    \ ]

  for fileName in triggerFiles
      let fileName = fnameescape(fileName)
      if filereadable(fileName)
          execute $'read {fileName}'
          normal! k
      endif
  endfor
endfunction

" Key Mappings #####################################################################################

nnoremap <F1>  :NERDTreeToggle \| wincmd p \| vertical resize 111 \| wincmd p<CR>
nnoremap <F2>  :NERDTreeFind<CR>
nnoremap <F3>  :'a,.!sort -fg<CR>
nnoremap <F4>  :IndentGuidesToggle<CR>
inoremap <F5>  <Esc>:call InsertDivider()<CR>
nnoremap <F6>  :set hlsearch!<CR>
nnoremap <F7>  :cp<CR>
nnoremap <F8>  :cwindow<CR>
nnoremap <F9>  :cn<CR>
nnoremap <F11> <Esc>:call StartDailyReview()<CR>

nnoremap <Leader>c :ALEGoToTypeDefinition<CR>
nnoremap <Leader>d :ALEGoToDefinition<CR>
nnoremap <Leader>e :ALEDetail<CR>
nnoremap <Leader>h :ALEHover<CR>
nnoremap <Leader>n :ALENext<CR>
nnoremap <Leader>p :ALEPrevious<CR>
nnoremap <Leader>r :ALEFindReferences<CR>
nnoremap <Leader>x :ALEToggle<CR>
nnoremap <Leader>w :w<CR>

nnoremap ' :BufExplorer<CR>

nnoremap j gj
nnoremap k gk

" Local Overrides ##################################################################################

silent! source $HOME/.vimrc.local    " user or machine specific .vimrc
silent! source .vimrc.local          " project specific .vimrc

" File-Type Specific Settings ######################################################################

autocmd BufRead COMMIT_EDITMSG set textwidth=70 colorcolumn=70
autocmd BufRead Makefile setlocal noexpandtab
autocmd BufRead *.scss setlocal shiftwidth=4
autocmd BufNewFile,BufRead *.md Wrapwidth 100 | setlocal textwidth=0 spell wrap
autocmd WinResized *.md Wrapwidth 100
autocmd FileType * setlocal formatoptions-=c formatoptions-=r formatoptions-=o

" Startup Commands #################################################################################

autocmd VimEnter * if argc() == 0 | NERDTree | wincmd p | vertical resize 111
autocmd CursorHold,FocusLost * silent! wall
autocmd FileType qf execute "resize " . float2nr(&lines * 1 / 3)
