# This file is a minimal clang-include-fixer vim-integration. To install:
# - Change 'binary' if clang-include-fixer is not on the path (see below).
# - Add to your .vimrc:
#
#   noremap <leader>cf :pyf path/to/llvm/source/tools/clang/tools/extra/clang-include-fixer/tool/clang-include-fixer.py<cr>
#
# This enables clang-include-fixer for NORMAL and VISUAL mode. Change
# "<leader>cf" to another binding if you need clang-include-fixer on a
# different key.
#
# To set up clang-include-fixer, see
# http://clang.llvm.org/extra/clang-include-fixer.html
#
# With this integration you can press the bound key and clang-include-fixer will
# be run on the current buffer.
#
# It operates on the current, potentially unsaved buffer and does not create
# or save any files. To revert a fix, just undo.

from __future__ import print_function
import argparse
import difflib
import json
import re
import subprocess
import vim

# set g:clang_include_fixer_path to the path to clang-include-fixer if it is not
# on the path.
# Change this to the full path if clang-include-fixer is not on the path.
binary = 'clang-include-fixer'
if vim.eval('exists("g:clang_include_fixer_path")') == "1":
  binary = vim.eval('g:clang_include_fixer_path')

maximum_suggested_headers = 3
if vim.eval('exists("g:clang_include_fixer_maximum_suggested_headers")') == "1":
  maximum_suggested_headers = max(
      1,
      vim.eval('g:clang_include_fixer_maximum_suggested_headers'))

increment_num = 5
if vim.eval('exists("g:clang_include_fixer_increment_num")') == "1":
  increment_num = max(
      1,
      vim.eval('g:clang_include_fixer_increment_num'))

jump_to_include = False
if vim.eval('exists("g:clang_include_fixer_jump_to_include")') == "1":
  jump_to_include = vim.eval('g:clang_include_fixer_jump_to_include') != "0"

query_mode = False
if vim.eval('exists("g:clang_include_fixer_query_mode")') == "1":
  query_mode = vim.eval('g:clang_include_fixer_query_mode') != "0"


def GetUserSelection(message, headers, maximum_suggested_headers):
  eval_message = message + '\n'
  for idx, header in enumerate(headers[0:maximum_suggested_headers]):
    eval_message += "({0}). {1}\n".format(idx + 1, header)
  eval_message += "Enter (q) to quit;"
  if maximum_suggested_headers < len(headers):
    eval_message += " (m) to show {0} more candidates.".format(
        min(increment_num, len(headers) - maximum_suggested_headers))

  eval_message += "\nSelect (default 1): "
  res = vim.eval("input('{0}')".format(eval_message))
  if res == '':
    # choose the top ranked header by default
    idx = 1
  elif res == 'q':
    raise Exception('   Insertion cancelled...')
  elif res == 'm':
    return GetUserSelection(message,
                            headers, maximum_suggested_headers + increment_num)
  else:
    try:
      idx = int(res)
      if idx <= 0 or idx > len(headers):
        raise Exception()
    except Exception:
      # Show a new prompt on invalid option instead of aborting so that users
      # don't need to wait for another clang-include-fixer run.
      print("Invalid option: {}".format(res), file=sys.stderr)
      return GetUserSelection(message, headers, maximum_suggested_headers)
  return headers[idx - 1]


def execute(command, text):
  # Avoid flashing a cmd prompt on Windows.
  startupinfo = None
  if sys.platform.startswith('win32'):
    startupinfo = subprocess.STARTUPINFO()
    startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
    startupinfo.wShowWindow = subprocess.SW_HIDE

  p = subprocess.Popen(command,
                       stdout=subprocess.PIPE, stderr=subprocess.PIPE,
                       stdin=subprocess.PIPE, startupinfo=startupinfo)
  return p.communicate(input=text.encode('utf-8'))


def InsertHeaderToVimBuffer(header, text):
  command = [binary, "-stdin", "-insert-header=" + json.dumps(header),
             vim.current.buffer.name]
  stdout, stderr = execute(command, text)
  if stderr:
    raise Exception(stderr)
  if stdout:
    lines = stdout.splitlines()
    sequence = difflib.SequenceMatcher(None, vim.current.buffer, lines)
    line_num = None
    for op in reversed(sequence.get_opcodes()):
      if op[0] != 'equal':
        vim.current.buffer[op[1]:op[2]] = lines[op[3]:op[4]]
      if op[0] == 'insert':
        # line_num in vim is 1-based.
        line_num = op[1] + 1

    if jump_to_include and line_num:
      vim.current.window.cursor = (line_num, 0)


# The vim internal implementation (expand("cword"/"cWORD")) doesn't support
# our use case very well, we re-implement our own one.
def get_symbol_under_cursor():
  line = vim.eval("line(\".\")")
  # column number in vim is 1-based.
  col = int(vim.eval("col(\".\")")) - 1
  line_text = vim.eval("getline({0})".format(line))
  if len(line_text) == 0: return ""
  symbol_pos_begin = col
  p = re.compile('[a-zA-Z0-9:_]')
  while symbol_pos_begin >= 0 and p.match(line_text[symbol_pos_begin]):
    symbol_pos_begin -= 1

  symbol_pos_end = col
  while symbol_pos_end < len(line_text) and p.match(line_text[symbol_pos_end]):
    symbol_pos_end += 1
  return line_text[symbol_pos_begin+1:symbol_pos_end]


def main():
  parser = argparse.ArgumentParser(
      description='Vim integration for clang-include-fixer')
  parser.add_argument('-db', default='yaml',
                      help='clang-include-fixer input format.')
  parser.add_argument('-input', default='',
                      help='String to initialize the database.')
  # Don't throw exception when parsing unknown arguments to make the script
  # work in neovim.
  # Neovim (at least v0.2.1) somehow mangles the sys.argv in a weird way: it
  # will pass additional arguments (e.g. "-c script_host.py") to sys.argv,
  # which makes the script fail.
  args, _ = parser.parse_known_args()

  # Get the current text.
  buf = vim.current.buffer
  text = '\n'.join(buf)

  if query_mode:
    symbol = get_symbol_under_cursor()
    if len(symbol) == 0:
      print("Skip querying empty symbol.")
      return
    command = [binary, "-stdin", "-query-symbol="+get_symbol_under_cursor(),
               "-db=" + args.db, "-input=" + args.input,
               vim.current.buffer.name]
  else:
    # Run command to get all headers.
    command = [binary, "-stdin", "-output-headers", "-db=" + args.db,
               "-input=" + args.input, vim.current.buffer.name]
  stdout, stderr = execute(command, text)
  if stderr:
    print("Error while running clang-include-fixer: {}".format(stderr),
          file=sys.stderr)
    return

  include_fixer_context = json.loads(stdout)
  query_symbol_infos = include_fixer_context["QuerySymbolInfos"]
  if not query_symbol_infos:
    print("The file is fine, no need to add a header.")
    return
  symbol = query_symbol_infos[0]["RawIdentifier"]
  # The header_infos is already sorted by clang-include-fixer.
  header_infos = include_fixer_context["HeaderInfos"]
  # Deduplicate headers while keeping the order, so that the same header would
  # not be suggested twice.
  unique_headers = []
  seen = set()
  for header_info in header_infos:
    header = header_info["Header"]
    if header not in seen:
      seen.add(header)
      unique_headers.append(header)

  if not unique_headers:
    print("Couldn't find a header for {0}.".format(symbol))
    return

  try:
    selected = unique_headers[0]
    inserted_header_infos = header_infos
    if len(unique_headers) > 1:
      selected = GetUserSelection(
          "choose a header file for {0}.".format(symbol),
          unique_headers, maximum_suggested_headers)
      inserted_header_infos = [
        header for header in header_infos if header["Header"] == selected]
    include_fixer_context["HeaderInfos"] = inserted_header_infos

    InsertHeaderToVimBuffer(include_fixer_context, text)
    print("Added #include {0} for {1}.".format(selected, symbol))
  except Exception as error:
    print(error, file=sys.stderr)
  return


if __name__ == '__main__':
  main()
