# Copyright 2019 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 os
import re
import sys


def GetScriptName():
  return os.path.basename(os.path.abspath(sys.argv[0]))


def GetJavaFilePath(java_package, class_name):
  package_path = java_package.replace('.', os.path.sep)
  file_name = class_name + '.java'
  return os.path.join(package_path, file_name)


def KCamelToShouty(s):
  """Convert |s| from kCamelCase or CamelCase to SHOUTY_CASE.

  kFooBar -> FOO_BAR
  FooBar -> FOO_BAR
  FooBAR9 -> FOO_BAR9
  FooBARBaz -> FOO_BAR_BAZ
  """
  if not re.match(r'^k?([A-Z][^A-Z]+|[A-Z0-9]+)+$', s):
    return s
  # Strip the leading k.
  s = re.sub(r'^k', '', s)
  # Treat "WebView" like one word.
  s = re.sub(r'WebView', r'Webview', s)
  # Add _ between title words and anything else.
  s = re.sub(r'([^_])([A-Z][^A-Z_0-9]+)', r'\1_\2', s)
  # Add _ between lower -> upper transitions.
  s = re.sub(r'([^A-Z_0-9])([A-Z])', r'\1_\2', s)
  return s.upper()


class JavaString(object):
  def __init__(self, name, value, comments):
    self.name = KCamelToShouty(name)
    self.value = value
    self.comments = '\n'.join('    ' + x for x in comments)

  def Format(self):
    return '%s\n    public static final String %s = %s;' % (
        self.comments, self.name, self.value)


def ParseTemplateFile(lines):
  package_re = re.compile(r'^package (.*);')
  class_re = re.compile(r'.*class (.*) {')
  package = ''
  class_name = ''
  for line in lines:
    package_line = package_re.match(line)
    if package_line:
      package = package_line.groups()[0]
    class_line = class_re.match(line)
    if class_line:
      class_name = class_line.groups()[0]
      break
  return package, class_name


# TODO(crbug.com/937282): Work will be needed if we want to annotate specific
# constants in the file to be parsed.
class CppConstantParser(object):
  """Parses C++ constants, retaining their comments.

  The Delegate subclass is responsible for matching and extracting the
  constant's variable name and value, as well as generating an object to
  represent the Java representation of this value.
  """
  SINGLE_LINE_COMMENT_RE = re.compile(r'\s*(// [^\n]*)')

  class Delegate(object):
    def ExtractConstantName(self, line):
      """Extracts a constant's name from line or None if not a match."""
      raise NotImplementedError()

    def ExtractValue(self, line):
      """Extracts a constant's value from line or None if not a match."""
      raise NotImplementedError()

    def CreateJavaConstant(self, name, value, comments):
      """Creates an object representing the Java analog of a C++ constant.

      CppConstantParser will not interact with the object created by this
      method. Instead, it will store this value in a list and return a list of
      all objects from the Parse() method. In this way, the caller may define
      whatever class suits their need.

      Args:
        name: the constant's variable name, as extracted by
          ExtractConstantName()
        value: the constant's value, as extracted by ExtractValue()
        comments: the code comments describing this constant
      """
      raise NotImplementedError()

  def __init__(self, delegate, lines):
    self._delegate = delegate
    self._lines = lines
    self._in_variable = False
    self._in_comment = False
    self._package = ''
    self._current_comments = []
    self._current_name = ''
    self._current_value = ''
    self._constants = []

  def _ExtractVariable(self, line):
    match = StringFileParser.STRING_RE.match(line)
    return match.group(1) if match else None

  def _ExtractValue(self, line):
    match = StringFileParser.VALUE_RE.search(line)
    return match.group(1) if match else None

  def _Reset(self):
    self._current_comments = []
    self._current_name = ''
    self._current_value = ''
    self._in_variable = False
    self._in_comment = False

  def _AppendConstant(self):
    self._constants.append(
        self._delegate.CreateJavaConstant(self._current_name,
                                          self._current_value,
                                          self._current_comments))
    self._Reset()

  def _ParseValue(self, line):
    current_value = self._delegate.ExtractValue(line)
    if current_value is not None:
      self._current_value = current_value
      self._AppendConstant()
    else:
      self._Reset()

  def _ParseComment(self, line):
    comment_line = CppConstantParser.SINGLE_LINE_COMMENT_RE.match(line)
    if comment_line:
      self._current_comments.append(comment_line.groups()[0])
      self._in_comment = True
      self._in_variable = True
      return True
    else:
      self._in_comment = False
      return False

  def _ParseVariable(self, line):
    current_name = self._delegate.ExtractConstantName(line)
    if current_name is not None:
      self._current_name = current_name
      current_value = self._delegate.ExtractValue(line)
      if current_value is not None:
        self._current_value = current_value
        self._AppendConstant()
      else:
        self._in_variable = True
      return True
    else:
      self._in_variable = False
      return False

  def _ParseLine(self, line):
    if not self._in_variable:
      if not self._ParseVariable(line):
        self._ParseComment(line)
      return

    if self._in_comment:
      if self._ParseComment(line):
        return
      if not self._ParseVariable(line):
        self._Reset()
      return

    if self._in_variable:
      self._ParseValue(line)

  def Parse(self):
    """Returns a list of objects representing C++ constants.

    Each object in the list was created by Delegate.CreateJavaValue().
    """
    for line in self._lines:
      self._ParseLine(line)
    return self._constants
