"=============================================================================
" statusline.vim --- SpaceVim statusline API
" Copyright (c) 2016-2020 Wang Shidong & Contributors
" Author: Wang Shidong < wsdjeg at 163.com >
" URL: https://spacevim.org
" License: GPLv3
"=============================================================================

let s:self = {}
if has('nvim')
  let s:self.__floating = SpaceVim#api#import('neovim#floating')
else
  let s:self.__floating = SpaceVim#api#import('vim#floating')
endif
let s:self.__buffer = SpaceVim#api#import('vim#buffer')
let s:self.__cmp = SpaceVim#api#import('vim#compatible')

function! s:self.check_width(len, sec, winwidth) abort
  return a:len + self.len(a:sec) < a:winwidth
endfunction

let s:self.__winid = -1
let s:self.__bufnr = -1

function! s:self.len(sec) abort
  let str = matchstr(a:sec, '%{.*}')
  if !empty(str)
    let pos = match(str, '}')
    return len(a:sec) - len(str) + len(eval(str[2:pos-1])) + 4
  else
    return len(a:sec) + 4
  endif
endfunction

function! s:self.eval(sec) abort
  return substitute(a:sec, '%{.*}', '', 'g')
endfunction

function! s:self.build(left_sections, right_sections, lsep, rsep, fname, tag, hi_a, hi_b, hi_c, hi_z, winwidth) abort
  let l = '%#' . a:hi_a . '#' . a:left_sections[0]
  let l .= '%#' . a:hi_a . '_' . a:hi_b . '#' . a:lsep
  let flag = 1
  let len = 0
  for sec in filter(a:left_sections[1:], '!empty(v:val)')
    if self.check_width(len, sec, a:winwidth)
      let len += self.len(sec)
      if flag == 1
        let l .= '%#' . a:hi_b . '#' . sec
        let l .= '%#' . a:hi_b . '_' . a:hi_c . '#' . a:lsep
      else
        let l .= '%#' . a:hi_c . '#' . sec
        let l .= '%#' . a:hi_c . '_' . a:hi_b . '#' . a:lsep
      endif
      let flag = flag * -1
    endif
  endfor
  let l = l[:len(a:lsep) * -1 - 1]
  if empty(a:right_sections)
    if flag == 1
      return l . '%#' . a:hi_c . '#'
    else
      return l . '%#' . a:hi_b . '#'
    endif
  endif
  if self.check_width(len, a:fname, a:winwidth)
    let len += self.len(a:fname)
    if flag == 1
      let l .= '%#' . a:hi_c . '_' . a:hi_z . '#' . a:lsep . '%#' . a:hi_z . '#' . a:fname . '%='
    else
      let l .= '%#' . a:hi_b . '_' . a:hi_z . '#' . a:lsep . '%#' . a:hi_z . '#' . a:fname . '%='
    endif
  else
    if flag == 1
      let l .= '%#' . a:hi_c . '_' . a:hi_z . '#' . a:lsep . '%='
    else
      let l .= '%#' . a:hi_b . '_' . a:hi_z . '#' . a:lsep . '%='
    endif
  endif
  if self.check_width(len, a:tag, a:winwidth) && g:spacevim_enable_statusline_tag
    let l .= '%#' . a:hi_z . '#' . a:tag
  endif
  let l .= '%#' . a:hi_b . '_' . a:hi_z . '#' . a:rsep
  let flag = 1
  for sec in filter(a:right_sections, '!empty(v:val)')
    if self.check_width(len, sec, a:winwidth)
      let len += self.len(sec)
      if flag == 1
        let l .= '%#' . a:hi_b . '#' . sec
        let l .= '%#' . a:hi_c . '_' . a:hi_b . '#' . a:rsep
      else
        let l .= '%#' . a:hi_c . '#' . sec
        let l .= '%#' . a:hi_b . '_' . a:hi_c . '#' . a:rsep
      endif
      let flag = flag * -1
    endif
  endfor
  return l[:-4]
endfunction

function! s:self.support_float() abort
  return self.__floating.exists()
endfunction

if has('nvim')
  function! s:self.opened() abort
    return win_id2tabwin(self.__winid)[0] == tabpagenr()
  endfunction
else
  function! s:self.opened() abort
    "tabpage" will be -1 for a global popup, zero for a popup on
    "the current tabpage and a positive number for a popup on
    "another tabpage.
    if exists('*popup_list')
      return index(popup_list(), self.__winid) != -1
    else
      return index([-1, 0], get(popup_getoptions(self.__winid), 'tabpage', -2)) != -1
    endif
  endfunction
endif

function! s:self.open_float(st) abort
  if !has_key(self, '__bufnr') || !bufexists(self.__bufnr)
    let self.__bufnr = self.__buffer.bufadd('')
  endif
  if has_key(self, '__winid') && self.opened()
  else
    let self.__winid = self.__floating.open_win(self.__bufnr,
          \ v:false,
          \ {
          \ 'relative': 'editor',
          \ 'width'   : &columns,
          \ 'height'  : 1,
          \ 'highlight' : 'SpaceVim_statusline_a_bold',
          \ 'row': &lines - 2 ,
          \ 'col': 0
          \ })
  endif
  call setbufvar(self.__bufnr, '&relativenumber', 0)
  call setbufvar(self.__bufnr, '&number', 0)
  call setbufvar(self.__bufnr, '&bufhidden', 'wipe')
  call setbufvar(self.__bufnr, '&cursorline', 0)
  call setbufvar(self.__bufnr, '&modifiable', 1)
  if exists('*nvim_buf_set_virtual_text')
    call setwinvar(win_id2win(self.__winid), '&cursorline', 0)
    call nvim_buf_set_virtual_text(
          \ self.__bufnr,
          \ -1,
          \ 0,
          \ a:st,
          \ {})
  else
    let l = ''
    for [str, hg] in a:st
      let l .= str
    endfor
    call self.__buffer.buf_set_lines(self.__bufnr, 0, -1, 0, [l])
    let begin = 1
    let end = 0
    for [str, hg] in a:st
      let end = strlen(str)
      call win_execute(self.__winid, 'call self.__cmp.matchaddpos(hg, [[1, begin, end]])')
      let begin += end
    endfor
  endif
  call setbufvar(self.__bufnr, '&modifiable', 0)
  return self.__winid
endfunction

if s:self.__floating.exists()
  function! s:self.close_float() abort
    if get(self, '__winid', -1) != -1
      call self.__floating.win_close(self.__winid, 1)
    endif
  endfunction
else
  function! s:self.close_float() abort
    if get(self, '__winid', -1) != -1 && win_id2tabwin(self.__winid)[0] == tabpagenr()
      noautocmd execute win_id2win(self.__winid).'wincmd w'
      noautocmd close
    endif
  endfunction
endif
function! SpaceVim#api#vim#statusline#get() abort
  return deepcopy(s:self)
endfunction

" vim:set et sw=2 cc=80 nowrap:
