" vim:tabstop=2:shiftwidth=2:expandtab:textwidth=99
" Vimwiki autoload plugin file
" Description: Path manipulation functions
" Home: https://github.com/vimwiki/vimwiki/



function! s:unixify(path) abort
  " Unixify Path:
  return substitute(a:path, '\', '/', 'g')
endfunction


function! s:windowsify(path) abort
  " Windowsify Path:
  return substitute(a:path, '/', '\', 'g')
endfunction


" Define: os specific path convertion
if vimwiki#u#is_windows()
  function! s:osxify(path) abort
    return s:windowsify(a:path)
  endfunction
else
  function! s:osxify(path) abort
    return s:unixify(a:path)
  endfunction
endif


function! vimwiki#path#chomp_slash(str) abort
  " Remove Delimiter: of last path (slash or backslash)
  return substitute(a:str, '[/\\]\+$', '', '')
endfunction


" Define: path-compare function, either case-sensitive or not, depending on OS.
if vimwiki#u#is_windows()
  function! vimwiki#path#is_equal(p1, p2) abort
    return a:p1 ==? a:p2
  endfunction
else
  function! vimwiki#path#is_equal(p1, p2) abort
    return a:p1 ==# a:p2
  endfunction
endif


function! vimwiki#path#normalize(path) abort
  " Collapse Sections: like /a/b/../c to /a/c and /a/b/./c to /a/b/c
  let path = a:path
  while 1
    let intermediateResult = substitute(path, '/[^/]\+/\.\.', '', '')
    let result = substitute(intermediateResult, '/\./', '/', '')
    if result ==# path
      break
    endif
    let path = result
  endwhile
  return result
endfunction


function! vimwiki#path#path_norm(path) abort
  " Normalize Path: \ -> / &&  /// -> / && resolve(symlinks)
  " return if scp
  if a:path =~# '^scp:' | return a:path | endif
  " convert backslash to slash
  let path = substitute(a:path, '\', '/', 'g')
  " treat multiple consecutive slashes as one path separator
  let path = substitute(path, '/\+', '/', 'g')
  " ensure that we are not fooled by a symbolic link
  return resolve(path)
endfunction


function! vimwiki#path#is_link_to_dir(link) abort
  " Check: if link is to a directory
  " It should be ended with \ or /.
  return a:link =~# '\m[/\\]$'
endfunction


function! vimwiki#path#abs_path_of_link(link) abort
  " Get: absolute path <- path relative to current file
  return vimwiki#path#normalize(expand('%:p:h').'/'.a:link)
endfunction


function! vimwiki#path#path_common_pfx(path1, path2) abort
  " Returns: longest common path prefix of 2 given paths.
  " Ex: '~/home/usrname/wiki', '~/home/usrname/wiki/shmiki' => '~/home/usrname/wiki'
  let p1 = split(a:path1, '[/\\]', 1)
  let p2 = split(a:path2, '[/\\]', 1)

  let idx = 0
  let minlen = min([len(p1), len(p2)])
  while (idx < minlen) && vimwiki#path#is_equal(p1[idx], p2[idx])
    let idx = idx + 1
  endwhile
  if idx == 0
    return ''
  else
    return join(p1[: idx-1], '/')
  endif
endfunction


function! vimwiki#path#wikify_path(path) abort
  " Convert: path -> full resolved slashed path
  let result = resolve(fnamemodify(a:path, ':p'))
  if vimwiki#u#is_windows()
    let result = substitute(result, '\\', '/', 'g')
  endif
  let result = vimwiki#path#chomp_slash(result)
  return result
endfunction


function! vimwiki#path#current_wiki_file() abort
  " Return: Current file path relative
  return vimwiki#path#wikify_path(expand('%:p'))
endfunction


function! vimwiki#path#relpath(dir, file) abort
  " Return: the relative path from a:dir to a:file
  " Check if dir here ('.') -> return file
  if empty(a:dir) || a:dir =~# '^\.[/\\]\?$'
    return a:file
  endif
  " Unixify && Expand in
  let s_dir = s:unixify(expand(a:dir))
  let s_file = s:unixify(expand(a:file))

  " Split path
  let dir = split(s_dir, '/')
  let file = split(s_file, '/')

  " Shorten loop till equality
  while (len(dir) > 0 && len(file) > 0) && vimwiki#path#is_equal(dir[0], file[0])
    call remove(dir, 0)
    call remove(file, 0)
  endwhile

  " Return './' if nothing left
  if empty(dir) && empty(file)
    return s:osxify('./')
  endif

  " Build path segment
  let segments = []
  for segment in dir
    let segments += ['..']
  endfor
  for segment in file
    let segments += [segment]
  endfor

  " Join segments
  let result_path = join(segments, '/')
  if a:file =~# '\m/$'
    let result_path .= '/'
  endif

  return result_path
endfunction


function! vimwiki#path#mkdir(path, ...) abort
  " Mkdir:
  " if the optional argument provided and nonzero,
  " it will ask before creating a directory
  " returns: 1 iff directory exists or successfully created
  let path = expand(a:path)

  if path =~# '^scp:'
    " we can not do much, so let's pretend everything is ok
    return 1
  endif

  if isdirectory(path)
    return 1
  else
    if !exists('*mkdir')
      return 0
    endif

    let path = vimwiki#path#chomp_slash(path)
    if vimwiki#u#is_windows() && !empty(vimwiki#vars#get_global('w32_dir_enc'))
      let path = iconv(path, &encoding, vimwiki#vars#get_global('w32_dir_enc'))
    endif

    if a:0 && a:1 && input('Vimwiki: Make new directory: '.path."\n [y]es/[N]o? ") !~? '^y'
      return 0
    endif

    call mkdir(path, 'p')
    return 1
  endif
endfunction


function! vimwiki#path#is_absolute(path) abort
  " Check: if path is absolute
  let res=0

  " Match 'C:' or '/' or '~'
  if vimwiki#u#is_windows()
    let res += a:path =~? '\m^\a:'
  else
    let res += a:path =~# '\m^/\|\~/'
  endif

  " Do not prepend root_path to scp files
  " See: https://vim.fandom.com/wiki/Editing_remote_files_via_scp_in_vim
  let res += a:path =~# '\m^scp:'

  return res
endfunction



function! s:get_wikifile_link(wikifile) abort
  return vimwiki#base#subdir(vimwiki#vars#get_wikilocal('path'), a:wikifile).
    \ fnamemodify(a:wikifile, ':t:r')
endfunction

function! vimwiki#path#PasteLink(wikifile) abort
  call append(line('.'), '[[/'.s:get_wikifile_link(a:wikifile).']]')
endfunction


if vimwiki#u#is_windows()
  " Combine: a directory and a file into one path, doesn't generate duplicate
  " path separator in case the directory is also having an ending / or \. This
  " is because on windows ~\vimwiki//.tags is invalid but ~\vimwiki/.tags is a
  " valid path.
  function! vimwiki#path#join_path(directory, file) abort
    let directory = vimwiki#path#chomp_slash(a:directory)
    let file = substitute(a:file, '\m^[\\/]\+', '', '')
    return directory . '/' . file
  endfunction
else
  function! vimwiki#path#join_path(directory, file) abort
    let directory = substitute(a:directory, '\m/\+$', '', '')
    let file = substitute(a:file, '\m^/\+', '', '')
    return directory . '/' . file
  endfunction
endif
