" TODO treat if local (see $HOME in all tests)
" TODO mutualise (to prettify output) mode(1) to check if in -Es or not
" TODO test tabnext in at least one travis job (without -Es)

" Declare tipical Vim preambule
  " vint: -ProhibitSetNoCompatible
  set nocompatible
  filetype plugin indent on
  syntax enable

" Usefull var: for one day, making tests on local
  let $TPLUGIN = '/testplugin'
  let $THOME = $HOME

" Set chrooted virtual runtime path
  let rtp = $ROOT . '/rtp.vim'
  if filereadable(rtp)
    execute 'source ' . rtp
  endif


" Load Vader
  let vader = $ROOT.'/vader'
  exe 'set runtimepath+='.vader


" Wikis configuration
  " Declare default syntax
  let vimwiki_default = {}
  let vimwiki_default.path = $HOME . '/testwiki'
  let vimwiki_default.path_html = $HOME . '/html/default'
  let vimwiki_default.template_path = $HOME . '/testwiki/templates/'
  let vimwiki_default.syntax = 'default'
  let vimwiki_default.ext = '.wiki'
  let vimwiki_default.name = 'DefaultSyntax'
  let vimwiki_default.base_url = 'https://example.com/'

  " Declare markdown syntax - https://github.github.com/gfm/
  let vimwiki_markdown = {}
  let vimwiki_markdown.path = $HOME . '/testmarkdown'
  let vimwiki_markdown.path_html = $HOME . '/html/markdown'
  let vimwiki_markdown.syntax = 'markdown'
  let vimwiki_markdown.ext = '.md'
  let vimwiki_markdown.name = 'MarkdownSyntax'

  " Declare mediawiki syntax - https://www.mediawiki.org/wiki/Help:Formatting
  let vimwiki_mediawiki = {}
  let vimwiki_mediawiki.path = $HOME . '/testmediawiki'
  let vimwiki_mediawiki.path_html = $HOME . '/html/mediawiki'
  let vimwiki_mediawiki.syntax = 'media'
  let vimwiki_mediawiki.ext = '.mw'
  let vimwiki_mediawiki.name = 'MediaWikiSyntax'

  " Declare default syntax with spaces
  let vimwiki_default_space = {}
  let vimwiki_default_space.path = $HOME . '/testwiki space'
  let vimwiki_default_space.path_html = $HOME . '/html/testwiki space'
  let vimwiki_default_space.template_path = $HOME . '/testwiki space/templates/'
  let vimwiki_default_space.syntax = 'default'
  let vimwiki_default_space.ext = '.wiki'
  let vimwiki_default_space.name = 'DefaultSyntax'
  let vimwiki_default_space.base_url = 'https://example.com/'

  " Register the 4 wikis
  let g:vimwiki_list = [vimwiki_default, vimwiki_markdown, vimwiki_mediawiki, vimwiki_default_space]
  let g:vimwiki_list_vimrc = [vimwiki_default, vimwiki_markdown, vimwiki_mediawiki, vimwiki_default_space]

  " Test VimwikiColorize and ,wc
  let g:vimwiki_color_dic = {
        \   'default': ['', '#d79921'],
        \   'red': ['#cc241d', ''],
        \   'bred': ['', '#cc241d'],
        \   'green': ['#98971a', ''],
        \   'bgreen': ['', '#98971a'],
        \   'yellow': ['#d79921', ''],
        \   'byellow': ['', '#d79921'],
        \   'blue': ['#458588', ''],
        \   'bblue': ['', '#458588'],
        \   'purple': ['#b16286', ''],
        \   'bpurple': ['', '#b16286'],
        \   'orange': ['#d65d0e', ''],
        \   'borange': ['', '#d65d0e'],
        \   'gray': ['#a89984', ''],
        \   'bgray': ['', '#a89984']}

" Set basic settings
  " Avoid more prompt
  set nomore
  set backspace=indent,eol,start
  set wildmode=longest:full,full
  set wildmenu
  set wildignorecase
  set splitbelow
  set splitright
  set timeoutlen=600
  set ignorecase
  set smartcase
  set hidden
  set laststatus=2
  set hlsearch


" Map
  " Map ctrl-p/n for history completion instead of up/down arrows
  cnoremap <C-p> <Up>
  cnoremap <C-n> <Down>

  " Map jj to go back to command mode
  inoremap jj <esc>

  " Use <C-L> to clear the highlighting of :set hlsearch and also preserve the
  " default behavior of redrawing the screen
  if maparg('<C-L>', 'n') ==# ''
      nnoremap <silent> <C-L> :nohlsearch<C-R>=has('diff')?'<Bar>diffupdate':''<CR><CR><C-L>
  endif

" Define functions
  function! CommentLine(msg)
    " Log current line and argument message
    " Called: in GFM copying like: https://github.github.com/gfm/#example-360 in syntax_markdown_gfm_typeface.vader
    Log 'Content: `' . getline('.') . '`'
    Log 'Comment: ' . a:msg
  endfunction
  command! -nargs=1 CommentLine call CommentLine(<args>)

  function! SetSyntax(vw_syn)
    " Change the syntax using a temporary wiki
    " Change extension and wiki_nr
    let index=0
    if a:vw_syn ==# 'default'
      let ext = 'wiki'
      let index=0
    elseif a:vw_syn ==# 'markdown'
      let ext = 'md'
      let index=1
    elseif a:vw_syn ==# 'media'
      let ext = 'mw'
      let index=2
    else
      Log 'ERROR: Invalid syntax "' . a:vw_syn . '" in SetSyntax()'
      Log 'NOTE: function only accepts "media" for setting mediawiki syntax'
      return
    endif

    " Change temporary wiki
    let path = expand('%:p:h')
    let new_temp_wiki_settings = {
          \ 'path': path,
          \ 'ext': ext,
          \ 'syntax': a:vw_syn,
          \ 'bullet_types': g:vimwiki_wikilocal_vars[index]['bullet_types'],
          \ }

    " Remove any temporary wikis each time this function is called.
    " This is necessary to ensure syntax is properly set when running multiple tests
    " NOTE: this assumes there are 3 defined wikis in the vimrc. The last wiki
    " contains default settings for temporary wikis (so there are always
    " num wikis in vimrc + 1)
    let num_wikis = len(g:vimwiki_wikilocal_vars)
    while  num_wikis > 4
      call remove(g:vimwiki_wikilocal_vars, num_wikis - 1)
      let num_wikis = num_wikis - 1
    endwhile

    " Add the new wiki
    call vimwiki#vars#add_temporary_wiki(new_temp_wiki_settings)
    call vimwiki#vars#set_bufferlocal('wiki_nr', 3)

    " Verify syntax was set correctly
    Assert vimwiki#vars#get_wikilocal('syntax') ==# a:vw_syn, 
          \ 'ERROR: Vimwiki syntax not set correctly: '
          \ . 'Want: ' . a:vw_syn . ' '
          \ . 'Have: ' . vimwiki#vars#get_wikilocal('syntax') 
  endfunction

  function! UnloadVimwiki()
    " Clear mappings so plugin can be reloaded
    " this is needed if running manually multiple times
    nmapclear

    " UNlet what can be
    " -- Note: getcompletion not present on vim7.3
    for i in ['g:vimwiki_commentstring',
          \ 'b:did_ftplugin',
          \ 'g:loaded_vimwiki',
          \ 'g:vimwiki_global_vars',
          \ 'g:vimwiki_wikilocal_vars',
          \ 'g:vimwiki_syntaxlocal_vars',
          \ 'g:vimwiki_list',
          \ ]
      if exists(i)
        exe 'unlet ' . i
      endif
    endfor

    " Unlet ftplugin:
    " -- Vader often staty in same buffer: [Vader-workbench]
    if exists('b:did_ftplugin')
      unlet b:did_ftplugin
    endif
  endfunction

  function! LoadVimwiki()
    " Source plugin
    runtime! plugin/vimwiki.vim
  endfunction

  function! ReloadVimwiki()
    " Reload plugin to change settings
    call UnloadVimwiki()

    " Reset list
    let g:vimwiki_list = g:vimwiki_list_vimrc

    call LoadVimwiki()
  endfunction

  function! ReloadVars()
    " vars#init will not reload syntax varaible if not set
    unlet g:vimwiki_syntaxlocal_vars
    call vimwiki#vars#init()
  endfunction

  function! CopyResources()
    " Copy wiki test resources so that vimtest user can write them
    call system('cp -r /testplugin/test/resources/* $HOME/')
    " Make diary directory
    call system('mkdir $HOME/testwiki/diary')
    call system('mkdir $HOME/testmarkdown/diary')
  endfunction

  function! DeleteHiddenBuffers()
    " Delete Hidden buffer, usefull to clean
    " See: https://stackoverflow.com/a/8459043/2544873
    let tpbl=[]
    call map(range(1, tabpagenr('$')), 'extend(tpbl, tabpagebuflist(v:val))')
    for buf in filter(range(1, bufnr('$')), 'bufexists(v:val) && index(tpbl, v:val)==-1')
      if bufname(buf) =~? 'Vader'
          continue
      endif
      silent execute 'bwipeout!' buf
    endfor
  endfunction

  function! WriteMe()
    " Write current file: helper to hide `set bt=`
    set buftype=
    write! %
  endfunction

  function! DeleteFile(path)
    " Delete a file <- path <string>
    let path = expand(a:path)
    " Delete file
    try
      call delete(path)
    catch | endtry
    " Delete Buffer
    try
      execute 'bwipeout! ' . path
    catch | endtry
  endfunction

  function! PrintCommand(cmd)
    " Print a command output to the buffer
    redir => message
    silent execute a:cmd
    redir END
    if empty(message)
      Log 'no output'
    else
      silent put=message
    endif
  endfunction

  function! DestroyVar(var)
    " Destroy a variable is exists (unlet)
    if ! exists(a:var) | return | endif
    execute 'unlet ' . a:var
  endfunction

  function! AssertTab(nr)
    " Assert current tab is desired tab
    " Vader is creating 2 tabs
    AssertEqual a:nr + 2, tabpagenr()
  endfunction

  function! ConvertWiki2Html()
    " Convert current buffer: wiki -> html
    " No side effect (if no bug)
    " Save fbuffer number (to come back)
    let g:buf_vader = bufnr('%')

    " Cut wiki content
    let wiki_content = getline(1, '$')
    1,$delete

    " Paste to a named file
    " Edit a new file in wiki_root
    edit $HOME/testwiki/test_Convert2Html.wiki
    " Ensure it is void
    1,$delete
    " Write wiki content
    call setline(1, wiki_content)
    " Dump buffer to disk
    call WriteMe()

    " Convert
    """""""""
    Vimwiki2HTML

    " Cut output
    edit $HOME/html/default/test_Convert2Html.html
    let html_content = getline(1, '$')
    1,$delete

    " Paste output in [Vader] buffer
    execute 'buffer ' . g:buf_vader
    call setline(1, html_content)

    " Delete files
    call DeleteFile('$HOME/html/default/test_Convert2Html.html')
    call DeleteFile('$HOME/testwiki/test_Convert2Html.wiki')
  endfunction

  function! ConvertWiki2Body()
    " Get only body
    call ConvertWiki2Html()

    " Empty b register
    let @b = ''

    " Copy body
    /<body>/+1,/<.body>/-1:g/^/y B

    " Delete All lines
    1,$d

    " Paste body
    0put! b

    " Remove last line
    0d
  endfunction

  function! GetSyntaxVimwiki(line, col)
    let res = GetSyntaxStack(a:line, a:col)
    if empty(res)
      return 'normal'
    endif
    return res[0]
  endfunction

  function! GetSyntaxGroup(...)
    " Get normalized syntax group: usefull for boldItalic Vs italicBold
    " Arg1: line
    " Arg2: column
    " -- Here, Vader's SyntaxAt is not enough
    " From: https://stackoverflow.com/questions/9464844
    let line = a:0 >= 1 ? a:1 : '.'
    let col = a:0 >= 2 ? a:2 : '.'

    let l:s = synID(line, col, 1)
    return synIDattr(synIDtrans(l:s), 'name')
  endfun

  function! GetSyntaxStack(...)
    " Debug helper
    " Arg1: line
    " Arg2: column
    let line = a:0 >= 1 ? a:1 : '.'
    let col = a:0 >= 2 ? a:2 : '.'
    if !exists('*synstack')
      return []
    endif
    let res = map(synstack(line, col), 'synIDattr(v:val, "name")')

    " For old vim version returning 0
    if type(res) == type(0) && res == 0
      return []
    endif

    return res
  endfunction

  function! AssertIfVersion(version, one, two)
    " Run Assert only if vim version is high enough
    if v:version < a:version | return | endif
    AssertEqual a:one, a:two
  endfunction

  function! GetHighlightTerm(group, term)
    " Get output of `hi group`
    "
    " From: https://vi.stackexchange.com/a/12294/5026
    " Return list ['bold','underline']
    "
    " Warning: must only be called if has("patch-7.4-2008")
    " Or rather:  If execute() exists - it's not available for all 7.4
    " versions.
    " https://github.com/vim/vim/commit/79815f1ec77406f2f21a618c053e5793b597db7a

    " Clause: Dot not work if not able
    if v:version < 800 && has('patch-7.4-2008') != 1 | return [] | endif

    " Store output of group to variable
    let out = execute('hi ' . a:group)

    " If links to, call parent
    let parent = matchstr(out, 'links to *\zs[^ \t\n\r]*')
    if parent !=# ''
      " Return list_of_parent, parent
      return GetHighlightTerm(parent, a:term)
    endif

    " Return the unique term we are looking for
    let stg = matchstr(out, a:term . '=\zs[^[:space:]]*')
    return split(stg, ',')
  endfunction


" Copy Wiki's Resources
call CopyResources()

" vim: ft=vim:sw=2
