#!/usr/bin/env python3
# A tool to parse the FormatStyle struct from Format.h and update the
# documentation in ../ClangFormatStyleOptions.rst automatically.
# Run from the directory in which this file is located to update the docs.

import inspect
import os
import re
import sys
from io import TextIOWrapper
from typing import Set

CLANG_DIR = os.path.join(os.path.dirname(__file__), '../..')
FORMAT_STYLE_FILE = os.path.join(CLANG_DIR, 'include/clang/Format/Format.h')
INCLUDE_STYLE_FILE = os.path.join(CLANG_DIR, 'include/clang/Tooling/Inclusions/IncludeStyle.h')
DOC_FILE = os.path.join(CLANG_DIR, 'docs/ClangFormatStyleOptions.rst')

PLURALS_FILE = os.path.join(os.path.dirname(__file__), 'plurals.txt')

plurals: Set[str] = set()
with open(PLURALS_FILE, 'a+') as f:
  f.seek(0)
  plurals = set(f.read().splitlines())

def substitute(text, tag, contents):
  replacement = '\n.. START_%s\n\n%s\n\n.. END_%s\n' % (tag, contents, tag)
  pattern = r'\n\.\. START_%s\n.*\n\.\. END_%s\n' % (tag, tag)
  return re.sub(pattern, '%s', text, flags=re.S) % replacement

def register_plural(singular: str, plural: str):
  if plural not in plurals:
    if not hasattr(register_plural, "generated_new_plural"):
      print('Plural generation: you can use '
      f'`git checkout -- {os.path.relpath(PLURALS_FILE)}` '
      'to reemit warnings or `git add` to include new plurals\n')
    register_plural.generated_new_plural = True

    plurals.add(plural)
    with open(PLURALS_FILE, 'a') as f:
      f.write(plural + '\n')
    cf = inspect.currentframe()
    lineno = ''
    if cf and cf.f_back:
      lineno = ':' + str(cf.f_back.f_lineno)
    print(f'{__file__}{lineno} check if plural of {singular} is {plural}', file=sys.stderr)
  return plural

def pluralize(word: str):
  lword = word.lower()
  if len(lword) >= 2 and lword[-1] == 'y' and lword[-2] not in 'aeiou':
    return register_plural(word, word[:-1] + 'ies')
  elif lword.endswith(('s', 'sh', 'ch', 'x', 'z')):
    return register_plural(word, word[:-1] + 'es')
  elif lword.endswith('fe'):
    return register_plural(word, word[:-2] + 'ves')
  elif lword.endswith('f') and not lword.endswith('ff'):
    return register_plural(word, word[:-1] + 'ves')
  else:
    return register_plural(word, word + 's')


def to_yaml_type(typestr: str):
  if typestr == 'bool':
    return 'Boolean'
  elif typestr == 'int':
    return 'Integer'
  elif typestr == 'unsigned':
    return 'Unsigned'
  elif typestr == 'std::string':
    return 'String'

  subtype, napplied = re.subn(r'^std::vector<(.*)>$', r'\1', typestr)
  if napplied == 1:
    return 'List of ' + pluralize(to_yaml_type(subtype))

  return typestr

def doxygen2rst(text):
  text = re.sub(r'<tt>\s*(.*?)\s*<\/tt>', r'``\1``', text)
  text = re.sub(r'\\c ([^ ,;\.]+)', r'``\1``', text)
  text = re.sub(r'\\\w+ ', '', text)
  return text

def indent(text, columns, indent_first_line=True):
  indent_str = ' ' * columns
  s = re.sub(r'\n([^\n])', '\n' + indent_str + '\\1', text, flags=re.S)
  if not indent_first_line or s.startswith('\n'):
    return s
  return indent_str + s

class Option(object):
  def __init__(self, name, opt_type, comment, version):
    self.name = name
    self.type = opt_type
    self.comment = comment.strip()
    self.enum = None
    self.nested_struct = None
    self.version = version

  def __str__(self):
    if self.version:
      s = '**%s** (``%s``) :versionbadge:`clang-format %s`\n%s' % (self.name, to_yaml_type(self.type), self.version,
                                 doxygen2rst(indent(self.comment, 2)))
    else:
      s = '**%s** (``%s``)\n%s' % (self.name, to_yaml_type(self.type),
                                 doxygen2rst(indent(self.comment, 2)))
    if self.enum and self.enum.values:
      s += indent('\n\nPossible values:\n\n%s\n' % self.enum, 2)
    if self.nested_struct:
      s += indent('\n\nNested configuration flags:\n\n%s\n' %self.nested_struct,
                  2)
    return s

class NestedStruct(object):
  def __init__(self, name, comment):
    self.name = name
    self.comment = comment.strip()
    self.values = []

  def __str__(self):
    return self.comment + '\n' + '\n'.join(map(str, self.values))

class NestedField(object):
  def __init__(self, name, comment):
    self.name = name
    self.comment = comment.strip()

  def __str__(self):
    return '\n* ``%s`` %s' % (
        self.name,
        doxygen2rst(indent(self.comment, 2, indent_first_line=False)))

class Enum(object):
  def __init__(self, name, comment):
    self.name = name
    self.comment = comment.strip()
    self.values = []

  def __str__(self):
    return '\n'.join(map(str, self.values))

class NestedEnum(object):
  def __init__(self, name, enumtype, comment, values):
    self.name = name
    self.comment = comment
    self.values = values
    self.type = enumtype

  def __str__(self):
    s = '\n* ``%s %s``\n%s' % (to_yaml_type(self.type), self.name,
                                 doxygen2rst(indent(self.comment, 2)))
    s += indent('\nPossible values:\n\n', 2)
    s += indent('\n'.join(map(str, self.values)), 2)
    return s

class EnumValue(object):
  def __init__(self, name, comment, config):
    self.name = name
    self.comment = comment
    self.config = config

  def __str__(self):
    return '* ``%s`` (in configuration: ``%s``)\n%s' % (
        self.name,
        re.sub('.*_', '', self.config),
        doxygen2rst(indent(self.comment, 2)))


class OptionsReader:
  def __init__(self, header: TextIOWrapper):
    self.header = header
    self.in_code_block = False
    self.code_indent = 0
    self.lineno = 0
    self.last_err_lineno = -1

  def __file_path(self):
    return os.path.relpath(self.header.name)

  def __print_line(self, line: str):
    print(f'{self.lineno:>6} | {line}', file=sys.stderr)

  def __warning(self, msg: str, line: str):
    print(f'{self.__file_path()}:{self.lineno}: warning: {msg}:', file=sys.stderr)
    self.__print_line(line)

  def __clean_comment_line(self, line: str):
    match = re.match(r'^/// (?P<indent> +)?\\code(\{.(?P<lang>\w+)\})?$', line)
    if match:
      if self.in_code_block:
        self.__warning('`\\code` in another `\\code`', line)
      self.in_code_block = True
      indent_str = match.group('indent')
      if not indent_str:
        indent_str = ''
      self.code_indent = len(indent_str)
      lang = match.group('lang')
      if not lang:
        lang = 'c++'
      return f'\n{indent_str}.. code-block:: {lang}\n\n'

    endcode_match = re.match(r'^/// +\\endcode$', line)
    if endcode_match:
      if not self.in_code_block:
        self.__warning('no correct `\\code` found before this `\\endcode`', line)
      self.in_code_block = False
      return ''

    # check code block indentation
    if (self.in_code_block and not line == '///' and not
        line.startswith('///  ' + ' ' * self.code_indent)):
      if self.last_err_lineno == self.lineno - 1:
        self.__print_line(line)
      else:
        self.__warning('code block should be indented', line)
      self.last_err_lineno = self.lineno

    match = re.match(r'^/// \\warning$', line)
    if match:
      return '\n.. warning:: \n\n'

    endwarning_match = re.match(r'^/// +\\endwarning$', line)
    if endwarning_match:
      return ''
    return line[4:] + '\n'

  def read_options(self):
    class State:
      BeforeStruct, Finished, InStruct, InNestedStruct, InNestedFieldComment, \
        InFieldComment, InEnum, InEnumMemberComment = range(8)
    state = State.BeforeStruct

    options = []
    enums = {}
    nested_structs = {}
    comment = ''
    enum = None
    nested_struct = None
    version = None

    for line in self.header:
      self.lineno += 1
      line = line.strip()
      if state == State.BeforeStruct:
        if line in ('struct FormatStyle {', 'struct IncludeStyle {'):
          state = State.InStruct
      elif state == State.InStruct:
        if line.startswith('///'):
          state = State.InFieldComment
          comment = self.__clean_comment_line(line)
        elif line == '};':
          state = State.Finished
          break
      elif state == State.InFieldComment:
        if line.startswith(r'/// \version'):
          match = re.match(r'/// \\version\s*(?P<version>[0-9.]+)*', line)
          if match:
            version = match.group('version')
        elif line.startswith('///'):
          comment += self.__clean_comment_line(line)
        elif line.startswith('enum'):
          state = State.InEnum
          name = re.sub(r'enum\s+(\w+)\s*(:((\s*\w+)+)\s*)?\{', '\\1', line)
          enum = Enum(name, comment)
        elif line.startswith('struct'):
          state = State.InNestedStruct
          name = re.sub(r'struct\s+(\w+)\s*\{', '\\1', line)
          nested_struct = NestedStruct(name, comment)
        elif line.endswith(';'):
          prefix = '// '
          if line.startswith(prefix):
            line = line[len(prefix):]
          state = State.InStruct
          field_type, field_name = re.match(r'([<>:\w(,\s)]+)\s+(\w+);',
                                            line).groups()

          if not version:
            self.__warning(f'missing version for {field_name}', line)
          option = Option(str(field_name), str(field_type), comment, version)
          options.append(option)
          version = None
        else:
          raise Exception('Invalid format, expected comment, field or enum\n' + line)
      elif state == State.InNestedStruct:
        if line.startswith('///'):
          state = State.InNestedFieldComment
          comment = self.__clean_comment_line(line)
        elif line == '};':
          state = State.InStruct
          nested_structs[nested_struct.name] = nested_struct
      elif state == State.InNestedFieldComment:
        if line.startswith('///'):
          comment += self.__clean_comment_line(line)
        else:
          state = State.InNestedStruct
          field_type, field_name = re.match(r'([<>:\w(,\s)]+)\s+(\w+);', line).groups()
          if field_type in enums:
            nested_struct.values.append(NestedEnum(field_name,
                                                   field_type,
                                                   comment,
                                                   enums[field_type].values))
          else:
            nested_struct.values.append(NestedField(field_type + " " + field_name, comment))

      elif state == State.InEnum:
        if line.startswith('///'):
          state = State.InEnumMemberComment
          comment = self.__clean_comment_line(line)
        elif line == '};':
          state = State.InStruct
          enums[enum.name] = enum
        else:
          # Enum member without documentation. Must be documented where the enum
          # is used.
          pass
      elif state == State.InEnumMemberComment:
        if line.startswith('///'):
          comment += self.__clean_comment_line(line)
        else:
          state = State.InEnum
          val = line.replace(',', '')
          pos = val.find(" // ")
          if pos != -1:
            config = val[pos + 4:]
            val = val[:pos]
          else:
            config = val
          enum.values.append(EnumValue(val, comment, config))
    if state != State.Finished:
      raise Exception('Not finished by the end of file')

    for option in options:
      if option.type not in ['bool', 'unsigned', 'int', 'std::string',
                             'std::vector<std::string>',
                             'std::vector<IncludeCategory>',
                             'std::vector<RawStringFormat>']:
        if option.type in enums:
          option.enum = enums[option.type]
        elif option.type in nested_structs:
          option.nested_struct = nested_structs[option.type]
        else:
          raise Exception('Unknown type: %s' % option.type)
    return options


with open(FORMAT_STYLE_FILE) as f:
  opts = OptionsReader(f).read_options()
with open(INCLUDE_STYLE_FILE) as f:
  opts += OptionsReader(f).read_options()

opts = sorted(opts, key=lambda x: x.name)
options_text = '\n\n'.join(map(str, opts))

with open(DOC_FILE) as f:
  contents = f.read()

contents = substitute(contents, 'FORMAT_STYLE_OPTIONS', options_text)

with open(DOC_FILE, 'wb') as output:
  output.write(contents.encode())
