" ============================================================================
" Vim Configuration
" Maintainer: srdusr
" ============================================================================

" ============================================================================
" Core Settings
" ============================================================================
set nocompatible
set encoding=utf-8
set fileencoding=utf-8
scriptencoding utf-8
set termguicolors
set mouse=a
set clipboard=unnamedplus
set hidden
set updatetime=300
set timeoutlen=500
set ttimeoutlen=10

" Performance
set ttyfast
set lazyredraw
set ttyscroll=3

" ============================================================================
" Display and UI Settings
" ============================================================================
set number
set relativenumber
set cursorline
set signcolumn=no
set showcmd
set showmode
set showmatch
set matchtime=2
set laststatus=2
set cmdheight=1
set scrolloff=8
set sidescrolloff=8
set sidescroll=1
set display=lastline
set nowrap
set linebreak
set showbreak=↪\

" Window behavior
set splitright
set splitbelow
set winminwidth=1
set winwidth=5

" ============================================================================
" Formatting and Indentation Settings
" ============================================================================
set autoindent
set smartindent
set expandtab
set tabstop=2
set shiftwidth=2
set softtabstop=2
set shiftround
set textwidth=80
set formatoptions+=j
" set colorcolumn=+1

" File-specific formatting
setlocal tabstop=4
setlocal shiftwidth=4
setlocal softtabstop=4
setlocal foldmethod=marker

" ============================================================================
" Search and Matching Settings
" ============================================================================
set hlsearch
set incsearch
set ignorecase
set smartcase
set showmatch
" set inccommand=split

" ============================================================================
" File Handling and Backup Settings
" ============================================================================
set autoread
set autowrite
set autochdir
set confirm
set fileformats=unix,dos,mac

" Backup and undo configuration
set backup
set writebackup
set backupcopy=yes
set undofile
set noswapfile
set backupdir=~/.cache/vim/backup//
set directory=~/.cache/vim/swap//
set undodir=~/.cache/vim/undo//
set undolevels=10000
set undoreload=10000

" Create necessary directories
let s:config_dir = expand('~/.vim')
let s:cache_dir = expand('~/.cache/vim')
let s:dirs = [
            \ s:cache_dir . '/backup',
            \ s:cache_dir . '/swap',
            \ s:cache_dir . '/undo',
            \ s:cache_dir . '/shada',
            \ s:config_dir . '/sessions',
            \ ]

for s:dir in s:dirs
    if !isdirectory(s:dir)
        call mkdir(s:dir, 'p', 0700)
    endif
endfor

" ============================================================================
" Completion and Command Line Settings
" ============================================================================
set omnifunc=syntaxcomplete#Complete
set complete=.,w,b,u,t,i,kspell
set completeopt=menu,menuone,noselect

" Wildmenu configuration
set wildmenu
set wildmode=longest:full,full
set wildignorecase
set wildignore+=*.o,*.obj,.git,*.rbc,*.pyc,__pycache__
set wildignore+=.git,.hg,.svn
set wildignore+=*.swp,*.swo
set wildignore+=*.DS_Store
set wildignore+=*.class

" ============================================================================
" Leader Keys
" ============================================================================
let mapleader = ";"
let maplocalleader = "\\"

" ============================================================================
" Navigation and Movement Mappings
" ============================================================================

" Tmux/Vim Navigation Function
function! SmartMove(direction, tmux_flag)
    let curwin = win_getid()
    execute 'wincmd ' . a:direction
    if win_getid() == curwin
        call system('tmux select-pane ' . a:tmux_flag)
    endif
endfunction

" Window navigation
nnoremap <silent> <C-h> :call SmartMove('h', '-L')<CR>
nnoremap <silent> <C-j> :call SmartMove('j', '-D')<CR>
nnoremap <silent> <C-k> :call SmartMove('k', '-U')<CR>
nnoremap <silent> <C-l> :call SmartMove('l', '-R')<CR>

" Split window horizontally
nnoremap <leader>- :split<CR>

" Split window vertically
nnoremap <leader>\ :vsplit<CR>

" Close the current window
nnoremap <leader>c <C-w>c

" Buffer navigation
nnoremap <silent> <leader>bn :bnext<CR>
nnoremap <silent> <leader>bp :bprevious<CR>
nnoremap <silent> <leader>bd :bdelete<CR>
nnoremap <silent> <leader>ba :%bdelete<CR>
nnoremap <silent> <leader>bl :ls<CR>:b<Space>

" Quickfix and location list
nnoremap ]q :cnext<CR>zz
nnoremap [q :cprev<CR>zz
nnoremap ]l :lnext<CR>zz
nnoremap [l :lprev<CR>zz

" ============================================================================
" File and Buffer Management Mappings
" ============================================================================
nnoremap <silent> <leader>w :w<CR>
nnoremap <silent> <leader>q :q<CR>
nnoremap <silent> <leader>wq :wq<CR>
nnoremap <silent> <leader>Q :qa!<CR>

" File operations
nnoremap <leader>f :Lex<CR>
noremap <leader>o :Explore<CR>
nnoremap <leader>rf :browse old<cr>

" Utility mappings
nnoremap <silent> <leader>r :registers<CR>
nnoremap <silent> <leader>m :redir @+<CR>:silent messages<CR>:redir END<CR>
nnoremap <silent> <leader>hx :call HexState()<CR>
nnoremap <buffer> <leader>h :help <C-R><C-W><CR>

" Format disable
cnoremap F! :noautocmd w<CR>

" ============================================================================
" Window and Terminal Mappings
" ============================================================================

" Window resizing
nnoremap <M-Up>    :resize -2<CR>
noremap <M-Down>  :resize +2<CR>
noremap <M-Left>  :vertical resize -2<CR>
noremap <M-Right> :vertical resize +2<CR>

" Terminal mode
nnoremap <silent> <C-t> :terminal<CR>
tnoremap <C-t> <C-\><C-n>:q!<CR>
tnoremap <Esc> <C-\><C-n>
tnoremap <C-h> <C-\><C-n><C-w>h
tnoremap <C-j> <C-\><C-n><C-w>j
tnoremap <C-k> <C-\><C-n><C-w>k
tnoremap <C-l> <C-\><C-n><C-w>l

" ============================================================================
" Text Editing and Visual Mode Mappings
" ============================================================================

" Insert mode shortcuts
inoremap jk <ESC>

" Visual mode operations
vnoremap J :m '>+1<CR>gv=gv
vnoremap K :m '>-2<CR>gv=gv
vnoremap < <gv
vnoremap > >gv

" Text formatting
nnoremap Q gqap

" Auto-closing pairs
inoremap [ []<left>
inoremap ( ()<left>
inoremap { {}<left>
inoremap /* /**/<left><left>

" ============================================================================
" Tab and Completion Functions
" ============================================================================

" Smart Tab Function
function! SmartIndentTab()
    let line = getline('.')
    let col = col('.') - 1

    if col == 0 || line[col - 1] =~ '^\s*$'
        return "\<C-T>"
    else
        return "\<tab>"
    endif
endfunction

" Tab mappings
silent! iunmap <tab>
inoremap <silent><expr> <tab> SmartIndentTab()
inoremap <expr> <CR> pumvisible() ? "\<C-Y>" : "\<CR>"

" Auto-completion function
function! AutoComplete()
    let skip_filetypes = ['netrw', 'help', 'startify', 'qf', 'man', 'gitcommit']

    if index(skip_filetypes, &filetype) >= 0
        return
    endif

    let col = col('.')
    if col < 4
        return
    endif

    let line = getline('.')
    let prev3 = line[col - 4]
    let prev2 = line[col - 3]
    let prev1 = line[col - 2]
    let curr  = v:char

    if curr =~ '\k' && prev3 !~ '\k' && prev2 =~ '\k' && prev1 =~ '\k'
        call feedkeys("\<C-n>", 'n')
    endif
endfunction

" ============================================================================
" Spell Checking
" ============================================================================
noremap <silent> <C-z> :setlocal spell!<CR>
setlocal nospell

function! SpellCheckStatus()
    return &spell ? ' [SPELL]' : ''
endfunction

" ============================================================================
" File Explorer Configuration
" ============================================================================
let g:netrw_banner=0
let g:netrw_browse_split=4
let g:netrw_altv=1
let g:netrw_liststyle=3
let g:netrw_fastbrowse = 0
let g:netrw_winsize=20

" ============================================================================
" Search Tools Configuration
" ============================================================================
if executable("rg")
    set grepprg=rg\ --vimgrep\ --no-heading
    set grepformat=%f:%l:%c:%m,%f:%l:%m
endif

" ============================================================================
" Clipboard Configuration
" ============================================================================

" OS Detection
let s:uname = substitute(system('uname'), '\n', '', '')
let g:is_mac = has('mac')
let g:is_linux = s:uname ==# 'Linux'
let g:is_windows = has('win32') || has('win64') || s:uname =~? 'Windows'
let g:is_wsl = has('wsl') || (g:is_linux && !empty($WSL_DISTRO_NAME))
let g:is_termux = has('termux') || (!empty($PREFIX) && $PREFIX =~# 'com.termux')
let g:is_wayland = !empty($WAYLAND_DISPLAY)
let g:is_x11 = !empty($DISPLAY) && empty($WAYLAND_DISPLAY)

" Clipboard configuration
if has('unnamedplus')
    set clipboard=unnamed,unnamedplus
else
    set clipboard=unnamed
endif

if has('clipboard')
    " Linux: Wayland/X11 providers
    if g:is_wayland && executable('wl-copy') && executable('wl-paste')
        let g:clipboard = {
                    \ 'name': 'wl-clipboard',
                    \ 'copy': {
                    \   '+': ['wl-copy', '--trim-newline'],
                    \   '*': ['wl-copy', '--trim-newline', '--primary'],
                    \ },
                    \ 'paste': {
                    \   '+': ['wl-paste', '--no-newline'],
                    \   '*': ['wl-paste', '--no-newline', '--primary'],
                    \ },
                    \ 'cache_enabled': 1,
                    \ }
    elseif g:is_x11 && executable('xclip')
        let g:clipboard = {
                    \ 'name': 'xclip',
                    \ 'copy': {
                    \   '+': ['xclip', '-selection', 'clipboard'],
                    \   '*': ['xclip', '-selection', 'primary'],
                    \ },
                    \ 'paste': {
                    \   '+': ['xclip', '-selection', 'clipboard', '-o'],
                    \   '*': ['xclip', '-selection', 'primary', '-o'],
                    \ },
                    \ 'cache_enabled': 1,
                    \ }
    elseif g:is_x11 && executable('xsel')
        let g:clipboard = {
                    \ 'name': 'xsel',
                    \ 'copy': {
                    \   '+': ['xsel', '--clipboard', '--input'],
                    \   '*': ['xsel', '--primary',   '--input'],
                    \ },
                    \ 'paste': {
                    \   '+': ['xsel', '--clipboard', '--output'],
                    \   '*': ['xsel', '--primary',   '--output'],
                    \ },
                    \ 'cache_enabled': 1,
                    \ }
    " macOS: pbcopy/pbpaste
    elseif g:is_mac && executable('pbcopy') && executable('pbpaste')
        let g:clipboard = {
                    \ 'name': 'macOS-clipboard',
                    \ 'copy':  { '+': ['pbcopy'], '*': ['pbcopy'] },
                    \ 'paste': { '+': ['pbpaste'], '*': ['pbpaste'] },
                    \ 'cache_enabled': 1,
                    \ }
    " WSL: prefer win32yank, fallback to clip.exe + PowerShell
    elseif g:is_wsl && executable('win32yank.exe')
        let g:clipboard = {
                    \ 'name': 'win32yank-wsl',
                    \ 'copy':  { '+': ['win32yank.exe', '-i', '--crlf'],
                    \            '*': ['win32yank.exe', '-i', '--crlf'] },
                    \ 'paste': { '+': ['win32yank.exe', '-o', '--lf'],
                    \            '*': ['win32yank.exe', '-o', '--lf'] },
                    \ 'cache_enabled': 1,
                    \ }
    elseif g:is_wsl && executable('clip.exe') && executable('powershell.exe')
        let g:clipboard = {
                    \ 'name': 'wsl-clip',
                    \ 'copy': {
                    \   '+': ['clip.exe'],
                    \   '*': ['clip.exe'],
                    \ },
                    \ 'paste': {
                    \   '+': ['powershell.exe', '-NoProfile', '-Command',
                    \          '[Console]::Out.Write((Get-Clipboard -Raw) -replace "`r","")'],
                    \   '*': ['powershell.exe', '-NoProfile', '-Command',
                    \          '[Console]::Out.Write((Get-Clipboard -Raw) -replace "`r","")'],
                    \ },
                    \ 'cache_enabled': 0,
                    \ }
    " Native Windows
    elseif g:is_windows && !g:is_wsl && executable('win32yank.exe')
        let g:clipboard = {
                    \ 'name': 'win32yank',
                    \ 'copy':  { '+': ['win32yank.exe', '-i', '--crlf'],
                    \            '*': ['win32yank.exe', '-i', '--crlf'] },
                    \ 'paste': { '+': ['win32yank.exe', '-o', '--lf'],
                    \            '*': ['win32yank.exe', '-o', '--lf'] },
                    \ 'cache_enabled': 1,
                    \ }
    elseif g:is_windows && !g:is_wsl && executable('powershell.exe')
        let g:clipboard = {
                    \ 'name': 'powershell-clipboard',
                    \ 'copy': {
                    \   '+': ['powershell.exe', '-NoProfile', '-Command',
                    \          'Set-Clipboard ([Console]::In.ReadToEnd())'],
                    \   '*': ['powershell.exe', '-NoProfile', '-Command',
                    \          'Set-Clipboard ([Console]::In.ReadToEnd())'],
                    \ },
                    \ 'paste': {
                    \   '+': ['powershell.exe', '-NoProfile', '-Command',
                    \          '[Console]::Out.Write((Get-Clipboard -Raw) -replace "`r","")'],
                    \   '*': ['powershell.exe', '-NoProfile', '-Command',
                    \          '[Console]::Out.Write((Get-Clipboard -Raw) -replace "`r","")'],
                    \ },
                    \ 'cache_enabled': 0,
                    \ }
    endif
endif

" ============================================================================
" Colorscheme and Appearance
" ============================================================================
syntax enable
set termguicolors
set guicursor=
let &t_SI = "\e[6 q"
let &t_EI = "\e[2 q"
set background=dark

" Window title
let progname = substitute($VIM, '.*[/\\]', '', '')
set title titlestring=%{progname}\ %f\ +%l\ #%{tabpagenr()}.%{winnr()}
if &term =~ '^screen' && !has('vim')
    exe "set t_ts=\e]2; t_fs=\7"
endif

colorscheme colorscheme

" ============================================================================
" Custom Functions
" ============================================================================

" Clear Terminal Buffer
function! ClearTerminal()
    if &buftype == 'terminal'
        let s:scroll_value = &scrollback
        set scrollback=1
        call feedkeys("\<C-\\>\<C-n>i")
        call feedkeys("clear\<CR>")
        call timer_start(100, {-> execute('let &scrollback=' . s:scroll_value)})
    endif
endfunction

" Rename Current File
function! RenameFile()
    let old_name = expand('%')
    let new_name = input('New file name: ', old_name, 'file')
    if new_name != '' && new_name != old_name
        try
            execute 'saveas ' . fnameescape(new_name)
            if filereadable(old_name) && !filereadable(new_name)
                call delete(old_name)
            endif
            redraw!
        catch /^Vim\%(\w\+\).*/
            echohl ErrorMsg | echo 'Error renaming file: ' . v:exception | echohl None
        endtry
    endif
endfunction

" Format with cursor preservation
function! PreserveCursorFormat()
    let l:pos = getpos(".")
    silent! normal! gg=G
    call setpos('.', l:pos)
endfunction

" File/URL opener
function! OpenFileOrUrl(path) abort
    if !exists('g:os_name')
        echohl WarningMsg | echom 'OS detection not available' | echohl None
        return
    endif

    let cmd = ''
    if g:os_name ==# 'mac'
        let cmd = 'open ' . shellescape(a:path)
    elseif g:os_name ==# 'linux'
        let cmd = 'xdg-open ' . shellescape(a:path) . ' >/dev/null 2>&1 &'
    elseif g:os_name ==# 'wsl'
        let cmd = 'wslview ' . shellescape(a:path) . ' >/dev/null 2>&1 &'
    elseif g:os_name ==# 'windows'
        let cmd = 'start "" ' . shellescape(a:path)
    elseif g:os_name ==# 'termux'
        let cmd = 'am start -a android.intent.action.VIEW -d ' . shellescape(a:path)
    else
        echohl WarningMsg | echom 'No file opener for OS: ' . g:os_name | echohl None
        return
    endif

    call system(cmd)
    if v:shell_error
        echohl ErrorMsg | echom 'Failed to open: ' . a:path | echohl None
    endif
endfunction

" ============================================================================
" Hex Editing Functions
" ============================================================================

" Convert to hex
function! DoHex() abort
    let current_file = expand('%:p')
    if empty(current_file)
        echohl ErrorMsg | echo 'No file name' | echohl None
        return
    endif

    let new_file = current_file . '.hex'
    try
        execute 'w !xxd > ' . fnameescape(new_file)
        echohl Directory | echo 'Hex file created: ' . new_file | echohl None
    catch /^Vim\%(\w\+\):/
        echohl ErrorMsg | echo 'Error creating hex file: ' . v:exception | echohl None
    endtry
endfunction

" Convert from hex
function! UndoHex() abort
    let current_file = expand('%:p')
    if empty(current_file)
        echohl ErrorMsg | echo 'No file name' | echohl None
        return
    endif

    let new_file = substitute(current_file, '\.hex$', '', '')
    if new_file ==# current_file
        echohl WarningMsg | echo 'Not a .hex file' | echohl None
        return
    endif

    try
        execute '%!xxd -r'
        execute 'w ' . fnameescape(new_file)
        echohl Directory | echo 'Binary file restored: ' . new_file | echohl None
    catch /^Vim\%(\w\+\):/
        echohl ErrorMsg | echo 'Error converting hex file: ' . v:exception | echohl None
    endtry
endfunction

" Hex state switcher
function! HexState() abort
    let choices = [
                \ '1. Convert to hex',
                \ '2. Convert from hex',
                \ '3. Cancel'
                \ ]

    let choice = inputlist(choices)
    if choice == 1
        call DoHex()
    elseif choice == 2
        call UndoHex()
    else
        echo 'Operation cancelled.'
    endif
endfunction

" ============================================================================
" Commands
" ============================================================================
command! -nargs=0 OpenFile call OpenFileOrUrl(expand('%:p'))

" ============================================================================
" Auto Commands
" ============================================================================

" Return to last position
augroup line_return
    au!
    au BufReadPost *
                \ if line("'\"") > 0 && line("'\"") <= line("$") |
                \     execute 'normal! g`"zvzz' |
                \ endif
augroup END

" Auto-completion
augroup AutoCompleteWordStart
    autocmd!
    autocmd InsertCharPre * call AutoComplete()
augroup END

" Relative numbers in insert mode
autocmd InsertEnter * set norelativenumber
autocmd InsertLeave * set relativenumber

" Netrw cleanup
autocmd FileType netrw setl bufhidden=wipe

" Reload config
augroup ReloadVimrc
    autocmd!
    autocmd BufWritePost $MYVIMRC nested source $MYVIMRC |
                \ doautocmd ColorScheme |
                \ call autoload#statusline#ActivateStatusline() |
                \ echon "Reloaded .vimrc" |
                \ redraw!
augroup END

" Auto format
augroup FormatOnSave
    autocmd!
    autocmd BufWritePre * call PreserveCursorFormat()
augroup END

" ============================================================================
" Statusline Configuration
" ============================================================================
let s:statusline_file = expand('~/.vim/autoload/statusline.vim')
if filereadable(s:statusline_file)
    execute 'source ' . fnameescape(s:statusline_file)

    augroup StatuslineConfig
        autocmd!
        autocmd VimEnter * call autoload#statusline#ActivateStatusline()
        autocmd ColorScheme * call autoload#statusline#UpdateStslineColors()
        autocmd VimEnter * redrawstatus!
    augroup END

    set laststatus=2
    set statusline=%!StatusLine()

    augroup StatuslineOverride
        autocmd!
        autocmd FileType help,gitcommit,netrw setlocal statusline=%f\ %h%m%r%=%-14.(%l,%c%V%)\ %P
    augroup END
endif

" ============================================================================
" GUI Configuration
" ============================================================================
if has('gui_running')
    color slate

    if has('mac')
        set guifont=Menlo\ Regular:h14
    elseif has('win32')
        set guifont=Consolas:h12
    else
        set guifont=Monospace\ 11
    endif

    set guioptions-=T
    set guioptions-=r
    set guioptions-=L
    set guioptions-=m

    autocmd VimEnter * :Lexplore | wincmd p
endif

" ============================================================================
" Final Setup
" ============================================================================
syntax on
filetype plugin indent on
setlocal keywordprg=:help
setlocal iskeyword+=:

" Load matchit for better % matching
if !exists('g:loaded_matchit') && findfile('plugin/matchit.vim', &rtp) ==# ''
    runtime! macros/matchit.vim
endif

" ============================================================================
