" don't spam the user when Vim is started in Vi compatibility mode
let s:cpo_save = &cpo
set cpo&vim

" go#lsp#lsp#Position returns the LSP text position. If no arguments are
" provided, the cursor position is assumed. Otherwise, there should be two
" arguments: the line and the column.
function! go#lsp#lsp#Position(...)
  if a:0 < 2
    let [l:line, l:col] = getpos('.')[1:2]
  else
    let l:line = a:1
    let l:col = a:2
  endif

  " LSP uses 0-based lines.
  return [l:line - 1, s:character(l:line, l:col)]
endfunction

function! s:strlen(str) abort
  let l:runes = split(a:str, '\zs')
  return len(l:runes) + len(filter(l:runes, 'char2nr(v:val)>=0x10000'))
endfunction

function! s:character(line, col) abort
  return s:strlen(getline(a:line)[:col([a:line, a:col - 1])])
endfunction

" go#lsp#PositionOf returns len(content[0:units]) where units is utf-16 code
" units. This is mostly useful for converting zero-based LSP text position to
" vim one-based position.
function! go#lsp#lsp#PositionOf(content, units, ...) abort
  if len(a:content) is 0
    return 0
  endif

  let l:remaining = a:units
  let l:str = ''
  for l:rune in split(a:content, '\zs')
    if l:remaining <= 0
      break
    endif
    let l:remaining -= 1
    if char2nr(l:rune) >= 0x10000
      let l:remaining -= 1
    endif
    let l:str = l:str . l:rune
  endfor

  return len(l:str) + 1
endfunction

function! go#lsp#lsp#SeverityToErrorType(severity) abort
  if a:severity == 1
    return 'E'
  elseif a:severity == 2
    return 'W'
  elseif a:severity == 3
    return 'I'
  elseif a:severity == 4
    return 'I'
  endif

  return ''
endfunction

" restore Vi compatibility settings
let &cpo = s:cpo_save
unlet s:cpo_save

" vim: sw=2 ts=2 et
