#!/usr/bin/env python3
#
# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import collections
from datetime import date
import re
import optparse
import os
from string import Template
import sys
import textwrap
import zipfile

from util import build_utils
from util import java_cpp_utils

# List of C++ types that are compatible with the Java code generated by this
# script.
#
# This script can parse .idl files however, at present it ignores special
# rules such as [cpp_enum_prefix_override="ax_attr"].
ENUM_FIXED_TYPE_ALLOWLIST = [
    'char', 'unsigned char', 'short', 'unsigned short', 'int', 'int8_t',
    'int16_t', 'int32_t', 'uint8_t', 'uint16_t'
]


class EnumDefinition(object):
  def __init__(self, original_enum_name=None, class_name_override=None,
               enum_package=None, entries=None, comments=None, fixed_type=None):
    self.original_enum_name = original_enum_name
    self.class_name_override = class_name_override
    self.enum_package = enum_package
    self.entries = collections.OrderedDict(entries or [])
    self.comments = collections.OrderedDict(comments or [])
    self.prefix_to_strip = None
    self.fixed_type = fixed_type

  def AppendEntry(self, key, value):
    if key in self.entries:
      raise Exception('Multiple definitions of key %s found.' % key)
    self.entries[key] = value

  def AppendEntryComment(self, key, value):
    if key in self.comments:
      raise Exception('Multiple definitions of key %s found.' % key)
    self.comments[key] = value

  @property
  def class_name(self):
    return self.class_name_override or self.original_enum_name

  def Finalize(self):
    self._Validate()
    self._AssignEntryIndices()
    self._StripPrefix()
    self._NormalizeNames()

  def _Validate(self):
    assert self.class_name
    assert self.enum_package
    assert self.entries
    if self.fixed_type and self.fixed_type not in ENUM_FIXED_TYPE_ALLOWLIST:
      raise Exception('Fixed type %s for enum %s not in allowlist.' %
                      (self.fixed_type, self.class_name))

  def _AssignEntryIndices(self):
    # Enums, if given no value, are given the value of the previous enum + 1.
    if not all(self.entries.values()):
      prev_enum_value = -1
      for key, value in self.entries.items():
        if not value:
          self.entries[key] = prev_enum_value + 1
        elif value in self.entries:
          self.entries[key] = self.entries[value]
        else:
          try:
            self.entries[key] = int(value)
          except ValueError:
            raise Exception('Could not interpret integer from enum value "%s" '
                            'for key %s.' % (value, key))
        prev_enum_value = self.entries[key]


  def _StripPrefix(self):
    prefix_to_strip = self.prefix_to_strip
    if not prefix_to_strip:
      shout_case = self.original_enum_name
      shout_case = re.sub('(?!^)([A-Z]+)', r'_\1', shout_case).upper()
      shout_case += '_'

      prefixes = [shout_case, self.original_enum_name,
                  'k' + self.original_enum_name]

      for prefix in prefixes:
        if all([w.startswith(prefix) for w in self.entries.keys()]):
          prefix_to_strip = prefix
          break
      else:
        prefix_to_strip = ''

    def StripEntries(entries):
      ret = collections.OrderedDict()
      for k, v in entries.items():
        stripped_key = k.replace(prefix_to_strip, '', 1)
        if isinstance(v, str):
          stripped_value = v.replace(prefix_to_strip, '')
        else:
          stripped_value = v
        ret[stripped_key] = stripped_value

      return ret

    self.entries = StripEntries(self.entries)
    self.comments = StripEntries(self.comments)

  def _NormalizeNames(self):
    self.entries = _TransformKeys(self.entries, java_cpp_utils.KCamelToShouty)
    self.comments = _TransformKeys(self.comments, java_cpp_utils.KCamelToShouty)


def _TransformKeys(d, func):
  """Normalize keys in |d| and update references to old keys in |d| values."""
  keys_map = {k: func(k) for k in d}
  ret = collections.OrderedDict()
  for k, v in d.items():
    # Need to transform values as well when the entry value was explicitly set
    # (since it could contain references to other enum entry values).
    if isinstance(v, str):
      # First check if a full replacement is available. This avoids issues when
      # one key is a substring of another.
      if v in d:
        v = keys_map[v]
      else:
        for old_key, new_key in keys_map.items():
          v = v.replace(old_key, new_key)
    ret[keys_map[k]] = v
  return ret


class DirectiveSet(object):
  class_name_override_key = 'CLASS_NAME_OVERRIDE'
  enum_package_key = 'ENUM_PACKAGE'
  prefix_to_strip_key = 'PREFIX_TO_STRIP'

  known_keys = [class_name_override_key, enum_package_key, prefix_to_strip_key]

  def __init__(self):
    self._directives = {}

  def Update(self, key, value):
    if key not in DirectiveSet.known_keys:
      raise Exception("Unknown directive: " + key)
    self._directives[key] = value

  @property
  def empty(self):
    return len(self._directives) == 0

  def UpdateDefinition(self, definition):
    definition.class_name_override = self._directives.get(
        DirectiveSet.class_name_override_key, '')
    definition.enum_package = self._directives.get(
        DirectiveSet.enum_package_key)
    definition.prefix_to_strip = self._directives.get(
        DirectiveSet.prefix_to_strip_key)


class HeaderParser(object):
  single_line_comment_re = re.compile(r'\s*//\s*([^\n]*)')
  multi_line_comment_start_re = re.compile(r'\s*/\*')
  enum_line_re = re.compile(r'^\s*(\w+)(\s*\=\s*([^,\n]+))?,?')
  enum_end_re = re.compile(r'^\s*}\s*;\.*$')
  generator_error_re = re.compile(r'^\s*//\s+GENERATED_JAVA_(\w+)\s*:\s*$')
  generator_directive_re = re.compile(
      r'^\s*//\s+GENERATED_JAVA_(\w+)\s*:\s*([\.\w]+)$')
  multi_line_generator_directive_start_re = re.compile(
      r'^\s*//\s+GENERATED_JAVA_(\w+)\s*:\s*\(([\.\w]*)$')
  multi_line_directive_continuation_re = re.compile(r'^\s*//\s+([\.\w]+)$')
  multi_line_directive_end_re = re.compile(r'^\s*//\s+([\.\w]*)\)$')

  optional_class_or_struct_re = r'(class|struct)?'
  enum_name_re = r'(\w+)'
  optional_fixed_type_re = r'(\:\s*(\w+\s*\w+?))?'
  enum_start_re = re.compile(r'^\s*(?:\[cpp.*\])?\s*enum\s+' +
      optional_class_or_struct_re + '\s*' + enum_name_re + '\s*' +
      optional_fixed_type_re + '\s*{\s*')
  enum_single_line_re = re.compile(
      r'^\s*(?:\[cpp.*\])?\s*enum.*{(?P<enum_entries>.*)}.*$')

  def __init__(self, lines, path=''):
    self._lines = lines
    self._path = path
    self._enum_definitions = []
    self._in_enum = False
    self._current_definition = None
    self._current_comments = []
    self._generator_directives = DirectiveSet()
    self._multi_line_generator_directive = None
    self._current_enum_entry = ''

  def _ApplyGeneratorDirectives(self):
    self._generator_directives.UpdateDefinition(self._current_definition)
    self._generator_directives = DirectiveSet()

  def ParseDefinitions(self):
    for line in self._lines:
      self._ParseLine(line)
    return self._enum_definitions

  def _ParseLine(self, line):
    if self._multi_line_generator_directive:
      self._ParseMultiLineDirectiveLine(line)
    elif not self._in_enum:
      self._ParseRegularLine(line)
    else:
      self._ParseEnumLine(line)

  def _ParseEnumLine(self, line):
    if HeaderParser.multi_line_comment_start_re.match(line):
      raise Exception('Multi-line comments in enums are not supported in ' +
                      self._path)

    enum_comment = HeaderParser.single_line_comment_re.match(line)
    if enum_comment:
      comment = enum_comment.groups()[0]
      if comment:
        self._current_comments.append(comment)
    elif HeaderParser.enum_end_re.match(line):
      self._FinalizeCurrentEnumDefinition()
    else:
      self._AddToCurrentEnumEntry(line)
      if ',' in line:
        self._ParseCurrentEnumEntry()

  def _ParseSingleLineEnum(self, line):
    for entry in line.split(','):
      self._AddToCurrentEnumEntry(entry)
      self._ParseCurrentEnumEntry()

    self._FinalizeCurrentEnumDefinition()

  def _ParseCurrentEnumEntry(self):
    if not self._current_enum_entry:
      return

    enum_entry = HeaderParser.enum_line_re.match(self._current_enum_entry)
    if not enum_entry:
      raise Exception('Unexpected error while attempting to parse %s as enum '
                      'entry.' % self._current_enum_entry)

    enum_key = enum_entry.groups()[0]
    enum_value = enum_entry.groups()[2]
    self._current_definition.AppendEntry(enum_key, enum_value)
    if self._current_comments:
      self._current_definition.AppendEntryComment(
          enum_key, ' '.join(self._current_comments))
      self._current_comments = []
    self._current_enum_entry = ''

  def _AddToCurrentEnumEntry(self, line):
    self._current_enum_entry += ' ' + line.strip()

  def _FinalizeCurrentEnumDefinition(self):
    if self._current_enum_entry:
      self._ParseCurrentEnumEntry()
    self._ApplyGeneratorDirectives()
    self._current_definition.Finalize()
    self._enum_definitions.append(self._current_definition)
    self._current_definition = None
    self._in_enum = False

  def _ParseMultiLineDirectiveLine(self, line):
    multi_line_directive_continuation = (
        HeaderParser.multi_line_directive_continuation_re.match(line))
    multi_line_directive_end = (
        HeaderParser.multi_line_directive_end_re.match(line))

    if multi_line_directive_continuation:
      value_cont = multi_line_directive_continuation.groups()[0]
      self._multi_line_generator_directive[1].append(value_cont)
    elif multi_line_directive_end:
      directive_name = self._multi_line_generator_directive[0]
      directive_value = "".join(self._multi_line_generator_directive[1])
      directive_value += multi_line_directive_end.groups()[0]
      self._multi_line_generator_directive = None
      self._generator_directives.Update(directive_name, directive_value)
    else:
      raise Exception('Malformed multi-line directive declaration in ' +
                      self._path)

  def _ParseRegularLine(self, line):
    enum_start = HeaderParser.enum_start_re.match(line)
    generator_directive_error = HeaderParser.generator_error_re.match(line)
    generator_directive = HeaderParser.generator_directive_re.match(line)
    multi_line_generator_directive_start = (
        HeaderParser.multi_line_generator_directive_start_re.match(line))
    single_line_enum = HeaderParser.enum_single_line_re.match(line)

    if generator_directive_error:
      raise Exception('Malformed directive declaration in ' + self._path +
                      '. Use () for multi-line directives. E.g.\n' +
                      '// GENERATED_JAVA_ENUM_PACKAGE: (\n' +
                      '//   foo.package)')
    elif generator_directive:
      directive_name = generator_directive.groups()[0]
      directive_value = generator_directive.groups()[1]
      self._generator_directives.Update(directive_name, directive_value)
    elif multi_line_generator_directive_start:
      directive_name = multi_line_generator_directive_start.groups()[0]
      directive_value = multi_line_generator_directive_start.groups()[1]
      self._multi_line_generator_directive = (directive_name, [directive_value])
    elif enum_start or single_line_enum:
      if self._generator_directives.empty:
        return
      self._current_definition = EnumDefinition(
          original_enum_name=enum_start.groups()[1],
          fixed_type=enum_start.groups()[3])
      self._in_enum = True
      if single_line_enum:
        self._ParseSingleLineEnum(single_line_enum.group('enum_entries'))


def DoGenerate(source_paths):
  for source_path in source_paths:
    enum_definitions = DoParseHeaderFile(source_path)
    if not enum_definitions:
      raise Exception('No enums found in %s\n'
                      'Did you forget prefixing enums with '
                      '"// GENERATED_JAVA_ENUM_PACKAGE: foo"?' %
                      source_path)
    for enum_definition in enum_definitions:
      output_path = java_cpp_utils.GetJavaFilePath(enum_definition.enum_package,
                                                   enum_definition.class_name)
      output = GenerateOutput(source_path, enum_definition)
      yield output_path, output


def DoParseHeaderFile(path):
  with open(path) as f:
    return HeaderParser(f.readlines(), path).ParseDefinitions()


def GenerateOutput(source_path, enum_definition):
  template = Template("""
// Copyright ${YEAR} The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// This file is autogenerated by
//     ${SCRIPT_NAME}
// From
//     ${SOURCE_PATH}

package ${PACKAGE};

import androidx.annotation.IntDef;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@IntDef({
${INT_DEF}
})
@Retention(RetentionPolicy.SOURCE)
public @interface ${CLASS_NAME} {
${ENUM_ENTRIES}
}
""")

  enum_template = Template('  int ${NAME} = ${VALUE};')
  enum_entries_string = []
  enum_names = []
  for enum_name, enum_value in enum_definition.entries.items():
    values = {
        'NAME': enum_name,
        'VALUE': enum_value,
    }
    enum_comments = enum_definition.comments.get(enum_name)
    if enum_comments:
      enum_comments_indent = '   * '
      comments_line_wrapper = textwrap.TextWrapper(
          initial_indent=enum_comments_indent,
          subsequent_indent=enum_comments_indent,
          width=100)
      enum_entries_string.append('  /**')
      enum_entries_string.append('\n'.join(
          comments_line_wrapper.wrap(enum_comments)))
      enum_entries_string.append('   */')
    enum_entries_string.append(enum_template.substitute(values))
    if enum_name != "NUM_ENTRIES":
      enum_names.append(enum_definition.class_name + '.' + enum_name)
  enum_entries_string = '\n'.join(enum_entries_string)

  enum_names_indent = ' ' * 4
  wrapper = textwrap.TextWrapper(initial_indent = enum_names_indent,
                                 subsequent_indent = enum_names_indent,
                                 width = 100)
  enum_names_string = '\n'.join(wrapper.wrap(', '.join(enum_names)))

  values = {
      'CLASS_NAME': enum_definition.class_name,
      'ENUM_ENTRIES': enum_entries_string,
      'PACKAGE': enum_definition.enum_package,
      'INT_DEF': enum_names_string,
      'SCRIPT_NAME': java_cpp_utils.GetScriptName(),
      'SOURCE_PATH': source_path,
      'YEAR': str(date.today().year)
  }
  return template.substitute(values)


def DoMain(argv):
  usage = 'usage: %prog [options] [output_dir] input_file(s)...'
  parser = optparse.OptionParser(usage=usage)

  parser.add_option('--srcjar',
                    help='When specified, a .srcjar at the given path is '
                    'created instead of individual .java files.')

  options, args = parser.parse_args(argv)

  if not args:
    parser.error('Need to specify at least one input file')
  input_paths = args

  with build_utils.AtomicOutput(options.srcjar) as f:
    with zipfile.ZipFile(f, 'w', zipfile.ZIP_STORED) as srcjar:
      for output_path, data in DoGenerate(input_paths):
        build_utils.AddToZipHermetic(srcjar, output_path, data=data)


if __name__ == '__main__':
  DoMain(sys.argv[1:])
