# 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.

"""Generates java source files from a mojom.Module."""

import argparse
import ast
import contextlib
import os
import re
import shutil
import sys
import tempfile

from jinja2 import contextfilter

import mojom.fileutil as fileutil
import mojom.generate.generator as generator
import mojom.generate.module as mojom
from mojom.generate.template_expander import UseJinja

sys.path.append(os.path.join(os.path.dirname(__file__), os.pardir,
                             os.pardir, os.pardir, os.pardir, os.pardir,
                             'build', 'android', 'gyp'))
from util import build_utils


GENERATOR_PREFIX = 'java'

_spec_to_java_type = {
  mojom.BOOL.spec: 'boolean',
  mojom.DCPIPE.spec: 'org.chromium.mojo.system.DataPipe.ConsumerHandle',
  mojom.DOUBLE.spec: 'double',
  mojom.DPPIPE.spec: 'org.chromium.mojo.system.DataPipe.ProducerHandle',
  mojom.FLOAT.spec: 'float',
  mojom.HANDLE.spec: 'org.chromium.mojo.system.UntypedHandle',
  mojom.INT16.spec: 'short',
  mojom.INT32.spec: 'int',
  mojom.INT64.spec: 'long',
  mojom.INT8.spec: 'byte',
  mojom.MSGPIPE.spec: 'org.chromium.mojo.system.MessagePipeHandle',
  mojom.NULLABLE_DCPIPE.spec:
      'org.chromium.mojo.system.DataPipe.ConsumerHandle',
  mojom.NULLABLE_DPPIPE.spec:
      'org.chromium.mojo.system.DataPipe.ProducerHandle',
  mojom.NULLABLE_HANDLE.spec: 'org.chromium.mojo.system.UntypedHandle',
  mojom.NULLABLE_MSGPIPE.spec: 'org.chromium.mojo.system.MessagePipeHandle',
  mojom.NULLABLE_SHAREDBUFFER.spec:
      'org.chromium.mojo.system.SharedBufferHandle',
  mojom.NULLABLE_STRING.spec: 'String',
  mojom.SHAREDBUFFER.spec: 'org.chromium.mojo.system.SharedBufferHandle',
  mojom.STRING.spec: 'String',
  mojom.UINT16.spec: 'short',
  mojom.UINT32.spec: 'int',
  mojom.UINT64.spec: 'long',
  mojom.UINT8.spec: 'byte',
}

_spec_to_decode_method = {
  mojom.BOOL.spec:                  'readBoolean',
  mojom.DCPIPE.spec:                'readConsumerHandle',
  mojom.DOUBLE.spec:                'readDouble',
  mojom.DPPIPE.spec:                'readProducerHandle',
  mojom.FLOAT.spec:                 'readFloat',
  mojom.HANDLE.spec:                'readUntypedHandle',
  mojom.INT16.spec:                 'readShort',
  mojom.INT32.spec:                 'readInt',
  mojom.INT64.spec:                 'readLong',
  mojom.INT8.spec:                  'readByte',
  mojom.MSGPIPE.spec:               'readMessagePipeHandle',
  mojom.NULLABLE_DCPIPE.spec:       'readConsumerHandle',
  mojom.NULLABLE_DPPIPE.spec:       'readProducerHandle',
  mojom.NULLABLE_HANDLE.spec:       'readUntypedHandle',
  mojom.NULLABLE_MSGPIPE.spec:      'readMessagePipeHandle',
  mojom.NULLABLE_SHAREDBUFFER.spec: 'readSharedBufferHandle',
  mojom.NULLABLE_STRING.spec:       'readString',
  mojom.SHAREDBUFFER.spec:          'readSharedBufferHandle',
  mojom.STRING.spec:                'readString',
  mojom.UINT16.spec:                'readShort',
  mojom.UINT32.spec:                'readInt',
  mojom.UINT64.spec:                'readLong',
  mojom.UINT8.spec:                 'readByte',
}

_java_primitive_to_boxed_type = {
  'boolean': 'Boolean',
  'byte':    'Byte',
  'double':  'Double',
  'float':   'Float',
  'int':     'Integer',
  'long':    'Long',
  'short':   'Short',
}

_java_reserved_types = [
  # These two may clash with commonly used classes on Android.
  'Manifest',
  'R'
]

def NameToComponent(name):
  """ Returns a list of lowercase words corresponding to a given name. """
  # Add underscores after uppercase letters when appropriate. An uppercase
  # letter is considered the end of a word if it is followed by an upper and a
  # lower. E.g. URLLoaderFactory -> URL_LoaderFactory
  name = re.sub('([A-Z][0-9]*)(?=[A-Z][0-9]*[a-z])', r'\1_', name)
  # Add underscores after lowercase letters when appropriate. A lowercase letter
  # is considered the end of a word if it is followed by an upper.
  # E.g. URLLoaderFactory -> URLLoader_Factory
  name = re.sub('([a-z][0-9]*)(?=[A-Z])', r'\1_', name)
  return [x.lower() for x in name.split('_')]

def UpperCamelCase(name):
  return ''.join([x.capitalize() for x in NameToComponent(name)])

def CamelCase(name):
  uccc = UpperCamelCase(name)
  return uccc[0].lower() + uccc[1:]

def ConstantStyle(name):
  components = NameToComponent(name)
  if components[0] == 'k' and len(components) > 1:
    components = components[1:]
  # variable cannot starts with a digit.
  if components[0][0].isdigit():
    components[0] = '_' + components[0]
  return '_'.join([x.upper() for x in components])

def GetNameForElement(element):
  if (mojom.IsEnumKind(element) or mojom.IsInterfaceKind(element) or
      mojom.IsStructKind(element) or mojom.IsUnionKind(element)):
    name = UpperCamelCase(element.name)
    if name in _java_reserved_types:
      return name + '_'
    return name
  if mojom.IsInterfaceRequestKind(element) or mojom.IsAssociatedKind(element):
    return GetNameForElement(element.kind)
  if isinstance(element, (mojom.Method,
                          mojom.Parameter,
                          mojom.Field)):
    return CamelCase(element.name)
  if isinstance(element,  mojom.EnumValue):
    return (GetNameForElement(element.enum) + '.' +
            ConstantStyle(element.name))
  if isinstance(element, (mojom.NamedValue,
                          mojom.Constant,
                          mojom.EnumField)):
    return ConstantStyle(element.name)
  raise Exception('Unexpected element: %s' % element)

def GetInterfaceResponseName(method):
  return UpperCamelCase(method.name + 'Response')

def ParseStringAttribute(attribute):
  assert isinstance(attribute, basestring)
  return attribute

def GetJavaTrueFalse(value):
  return 'true' if value else 'false'

def GetArrayNullabilityFlags(kind):
    """Returns nullability flags for an array type, see Decoder.java.

    As we have dedicated decoding functions for arrays, we have to pass
    nullability information about both the array itself, as well as the array
    element type there.
    """
    assert mojom.IsArrayKind(kind)
    ARRAY_NULLABLE   = \
        'org.chromium.mojo.bindings.BindingsHelper.ARRAY_NULLABLE'
    ELEMENT_NULLABLE = \
        'org.chromium.mojo.bindings.BindingsHelper.ELEMENT_NULLABLE'
    NOTHING_NULLABLE = \
        'org.chromium.mojo.bindings.BindingsHelper.NOTHING_NULLABLE'

    flags_to_set = []
    if mojom.IsNullableKind(kind):
        flags_to_set.append(ARRAY_NULLABLE)
    if mojom.IsNullableKind(kind.kind):
        flags_to_set.append(ELEMENT_NULLABLE)

    if not flags_to_set:
        flags_to_set = [NOTHING_NULLABLE]
    return ' | '.join(flags_to_set)


def AppendEncodeDecodeParams(initial_params, context, kind, bit):
  """ Appends standard parameters shared between encode and decode calls. """
  params = list(initial_params)
  if (kind == mojom.BOOL):
    params.append(str(bit))
  if mojom.IsReferenceKind(kind):
    if mojom.IsArrayKind(kind):
      params.append(GetArrayNullabilityFlags(kind))
    else:
      params.append(GetJavaTrueFalse(mojom.IsNullableKind(kind)))
  if mojom.IsArrayKind(kind):
    params.append(GetArrayExpectedLength(kind))
  if mojom.IsInterfaceKind(kind):
    params.append('%s.MANAGER' % GetJavaType(context, kind))
  if mojom.IsArrayKind(kind) and mojom.IsInterfaceKind(kind.kind):
    params.append('%s.MANAGER' % GetJavaType(context, kind.kind))
  return params


@contextfilter
def DecodeMethod(context, kind, offset, bit):
  def _DecodeMethodName(kind):
    if mojom.IsArrayKind(kind):
      return _DecodeMethodName(kind.kind) + 's'
    if mojom.IsEnumKind(kind):
      return _DecodeMethodName(mojom.INT32)
    if mojom.IsInterfaceRequestKind(kind):
      return 'readInterfaceRequest'
    if mojom.IsInterfaceKind(kind):
      return 'readServiceInterface'
    if mojom.IsAssociatedInterfaceRequestKind(kind):
      return 'readAssociatedInterfaceRequestNotSupported'
    if mojom.IsAssociatedInterfaceKind(kind):
      return 'readAssociatedServiceInterfaceNotSupported'
    return _spec_to_decode_method[kind.spec]
  methodName = _DecodeMethodName(kind)
  params = AppendEncodeDecodeParams([ str(offset) ], context, kind, bit)
  return '%s(%s)' % (methodName, ', '.join(params))

@contextfilter
def EncodeMethod(context, kind, variable, offset, bit):
  params = AppendEncodeDecodeParams(
      [ variable, str(offset) ], context, kind, bit)
  return 'encode(%s)' % ', '.join(params)

def GetPackage(module):
  if module.attributes and 'JavaPackage' in module.attributes:
    return ParseStringAttribute(module.attributes['JavaPackage'])
  # Default package.
  if module.namespace:
    return 'org.chromium.' + module.namespace
  return 'org.chromium'

def GetNameForKind(context, kind):
  def _GetNameHierachy(kind):
    hierachy = []
    if kind.parent_kind:
      hierachy = _GetNameHierachy(kind.parent_kind)
    hierachy.append(GetNameForElement(kind))
    return hierachy

  module = context.resolve('module')
  elements = []
  if GetPackage(module) != GetPackage(kind.module):
    elements += [GetPackage(kind.module)]
  elements += _GetNameHierachy(kind)
  return '.'.join(elements)

@contextfilter
def GetJavaClassForEnum(context, kind):
  return GetNameForKind(context, kind)

def GetBoxedJavaType(context, kind, with_generics=True):
  unboxed_type = GetJavaType(context, kind, False, with_generics)
  if unboxed_type in _java_primitive_to_boxed_type:
    return _java_primitive_to_boxed_type[unboxed_type]
  return unboxed_type

@contextfilter
def GetJavaType(context, kind, boxed=False, with_generics=True):
  if boxed:
    return GetBoxedJavaType(context, kind)
  if (mojom.IsStructKind(kind) or
      mojom.IsInterfaceKind(kind) or
      mojom.IsUnionKind(kind)):
    return GetNameForKind(context, kind)
  if mojom.IsInterfaceRequestKind(kind):
    return ('org.chromium.mojo.bindings.InterfaceRequest<%s>' %
            GetNameForKind(context, kind.kind))
  if mojom.IsAssociatedInterfaceKind(kind):
    return 'org.chromium.mojo.bindings.AssociatedInterfaceNotSupported'
  if mojom.IsAssociatedInterfaceRequestKind(kind):
    return 'org.chromium.mojo.bindings.AssociatedInterfaceRequestNotSupported'
  if mojom.IsMapKind(kind):
    if with_generics:
      return 'java.util.Map<%s, %s>' % (
          GetBoxedJavaType(context, kind.key_kind),
          GetBoxedJavaType(context, kind.value_kind))
    else:
      return 'java.util.Map'
  if mojom.IsArrayKind(kind):
    return '%s[]' % GetJavaType(context, kind.kind, boxed, with_generics)
  if mojom.IsEnumKind(kind):
    return 'int'
  return _spec_to_java_type[kind.spec]

@contextfilter
def DefaultValue(context, field):
  assert field.default
  if isinstance(field.kind, mojom.Struct):
    assert field.default == 'default'
    return 'new %s()' % GetJavaType(context, field.kind)
  return '(%s) %s' % (
      GetJavaType(context, field.kind),
      ExpressionToText(context, field.default, kind_spec=field.kind.spec))

@contextfilter
def ConstantValue(context, constant):
  return '(%s) %s' % (
      GetJavaType(context, constant.kind),
      ExpressionToText(context, constant.value, kind_spec=constant.kind.spec))

@contextfilter
def NewArray(context, kind, size):
  if mojom.IsArrayKind(kind.kind):
    return NewArray(context, kind.kind, size) + '[]'
  return 'new %s[%s]' % (
      GetJavaType(context, kind.kind, boxed=False, with_generics=False), size)

@contextfilter
def ExpressionToText(context, token, kind_spec=''):
  def _TranslateNamedValue(named_value):
    entity_name = GetNameForElement(named_value)
    if named_value.parent_kind:
      return GetJavaType(context, named_value.parent_kind) + '.' + entity_name
    # Handle the case where named_value is a module level constant:
    if not isinstance(named_value, mojom.EnumValue):
      entity_name = (GetConstantsMainEntityName(named_value.module) + '.' +
                      entity_name)
    if GetPackage(named_value.module) == GetPackage(context.resolve('module')):
      return entity_name
    return GetPackage(named_value.module) + '.' + entity_name

  if isinstance(token, mojom.NamedValue):
    return _TranslateNamedValue(token)
  if kind_spec.startswith('i') or kind_spec.startswith('u'):
    # Add Long suffix to all integer literals.
    number = ast.literal_eval(token.lstrip('+ '))
    if not isinstance(number, (int, long)):
      raise ValueError('got unexpected type %r for int literal %r' % (
          type(number), token))
    # If the literal is too large to fit a signed long, convert it to the
    # equivalent signed long.
    if number >= 2 ** 63:
      number -= 2 ** 64
    return '%dL' % number
  if isinstance(token, mojom.BuiltinValue):
    if token.value == 'double.INFINITY':
      return 'java.lang.Double.POSITIVE_INFINITY'
    if token.value == 'double.NEGATIVE_INFINITY':
      return 'java.lang.Double.NEGATIVE_INFINITY'
    if token.value == 'double.NAN':
      return 'java.lang.Double.NaN'
    if token.value == 'float.INFINITY':
      return 'java.lang.Float.POSITIVE_INFINITY'
    if token.value == 'float.NEGATIVE_INFINITY':
      return 'java.lang.Float.NEGATIVE_INFINITY'
    if token.value == 'float.NAN':
      return 'java.lang.Float.NaN'
  return token

def GetArrayKind(kind, size = None):
  if size is None:
    return mojom.Array(kind)
  else:
    array = mojom.Array(kind, 0)
    array.java_map_size = size
    return array

def GetArrayExpectedLength(kind):
  if mojom.IsArrayKind(kind) and kind.length is not None:
    return getattr(kind, 'java_map_size', str(kind.length))
  else:
    return 'org.chromium.mojo.bindings.BindingsHelper.UNSPECIFIED_ARRAY_LENGTH'

def IsPointerArrayKind(kind):
  if not mojom.IsArrayKind(kind):
    return False
  sub_kind = kind.kind
  return mojom.IsObjectKind(sub_kind) and not mojom.IsUnionKind(sub_kind)

def IsUnionArrayKind(kind):
  if not mojom.IsArrayKind(kind):
    return False
  sub_kind = kind.kind
  return mojom.IsUnionKind(sub_kind)

def GetConstantsMainEntityName(module):
  if module.attributes and 'JavaConstantsClassName' in module.attributes:
    return ParseStringAttribute(module.attributes['JavaConstantsClassName'])
  # This constructs the name of the embedding classes for module level constants
  # by extracting the mojom's filename and prepending it to Constants.
  return (UpperCamelCase(module.path.split('/')[-1].rsplit('.', 1)[0]) +
          'Constants')

def GetMethodOrdinalName(method):
  return ConstantStyle(method.name) + '_ORDINAL'

def HasMethodWithResponse(interface):
  for method in interface.methods:
    if method.response_parameters is not None:
      return True
  return False

def HasMethodWithoutResponse(interface):
  for method in interface.methods:
    if method.response_parameters is None:
      return True
  return False

@contextlib.contextmanager
def TempDir():
  dirname = tempfile.mkdtemp()
  try:
    yield dirname
  finally:
    shutil.rmtree(dirname)

class Generator(generator.Generator):
  def _GetJinjaExports(self):
    return {
      'package': GetPackage(self.module),
    }

  @staticmethod
  def GetTemplatePrefix():
    return "java_templates"

  def GetFilters(self):
    java_filters = {
      'array_expected_length': GetArrayExpectedLength,
      'array': GetArrayKind,
      'constant_value': ConstantValue,
      'decode_method': DecodeMethod,
      'default_value': DefaultValue,
      'encode_method': EncodeMethod,
      'expression_to_text': ExpressionToText,
      'has_method_without_response': HasMethodWithoutResponse,
      'has_method_with_response': HasMethodWithResponse,
      'interface_response_name': GetInterfaceResponseName,
      'is_array_kind': mojom.IsArrayKind,
      'is_any_handle_kind': mojom.IsAnyHandleKind,
      "is_enum_kind": mojom.IsEnumKind,
      'is_interface_request_kind': mojom.IsInterfaceRequestKind,
      'is_map_kind': mojom.IsMapKind,
      'is_nullable_kind': mojom.IsNullableKind,
      'is_pointer_array_kind': IsPointerArrayKind,
      'is_reference_kind': mojom.IsReferenceKind,
      'is_struct_kind': mojom.IsStructKind,
      'is_union_array_kind': IsUnionArrayKind,
      'is_union_kind': mojom.IsUnionKind,
      'java_class_for_enum': GetJavaClassForEnum,
      'java_true_false': GetJavaTrueFalse,
      'java_type': GetJavaType,
      'method_ordinal_name': GetMethodOrdinalName,
      'name': GetNameForElement,
      'new_array': NewArray,
      'ucc': lambda x: UpperCamelCase(x.name),
    }
    return java_filters

  def _GetJinjaExportsForInterface(self, interface):
    exports = self._GetJinjaExports()
    exports.update({'interface': interface})
    return exports

  @UseJinja('enum.java.tmpl')
  def _GenerateEnumSource(self, enum):
    exports = self._GetJinjaExports()
    exports.update({'enum': enum})
    return exports

  @UseJinja('struct.java.tmpl')
  def _GenerateStructSource(self, struct):
    exports = self._GetJinjaExports()
    exports.update({'struct': struct})
    return exports

  @UseJinja('union.java.tmpl')
  def _GenerateUnionSource(self, union):
    exports = self._GetJinjaExports()
    exports.update({'union': union})
    return exports

  @UseJinja('interface.java.tmpl')
  def _GenerateInterfaceSource(self, interface):
    return self._GetJinjaExportsForInterface(interface)

  @UseJinja('interface_internal.java.tmpl')
  def _GenerateInterfaceInternalSource(self, interface):
    return self._GetJinjaExportsForInterface(interface)

  @UseJinja('constants.java.tmpl')
  def _GenerateConstantsSource(self, module):
    exports = self._GetJinjaExports()
    exports.update({'main_entity': GetConstantsMainEntityName(module),
                    'constants': module.constants})
    return exports

  def _DoGenerateFiles(self):
    fileutil.EnsureDirectoryExists(self.output_dir)

    for struct in self.module.structs:
      self.Write(self._GenerateStructSource(struct),
                 '%s.java' % GetNameForElement(struct))

    for union in self.module.unions:
      self.Write(self._GenerateUnionSource(union),
                 '%s.java' % GetNameForElement(union))

    for enum in self.module.enums:
      self.Write(self._GenerateEnumSource(enum),
                 '%s.java' % GetNameForElement(enum))

    for interface in self.module.interfaces:
      self.Write(self._GenerateInterfaceSource(interface),
                 '%s.java' % GetNameForElement(interface))
      self.Write(self._GenerateInterfaceInternalSource(interface),
                 '%s_Internal.java' % GetNameForElement(interface))

    if self.module.constants:
      self.Write(self._GenerateConstantsSource(self.module),
                 '%s.java' % GetConstantsMainEntityName(self.module))

  def GenerateFiles(self, unparsed_args):
    # TODO(rockot): Support variant output for Java.
    if self.variant:
      raise Exception("Variants not supported in Java bindings.")

    self.module.Stylize(generator.Stylizer())

    parser = argparse.ArgumentParser()
    parser.add_argument('--java_output_directory', dest='java_output_directory')
    args = parser.parse_args(unparsed_args)
    package_path = GetPackage(self.module).replace('.', '/')

    # Generate the java files in a temporary directory and place a single
    # srcjar in the output directory.
    basename = "%s.srcjar" % self.module.path
    zip_filename = os.path.join(self.output_dir, basename)
    with TempDir() as temp_java_root:
      self.output_dir = os.path.join(temp_java_root, package_path)
      self._DoGenerateFiles();
      build_utils.ZipDir(zip_filename, temp_java_root)

    if args.java_output_directory:
      # If requested, generate the java files directly into indicated directory.
      self.output_dir = os.path.join(args.java_output_directory, package_path)
      self._DoGenerateFiles();

  def GetJinjaParameters(self):
    return {
      'lstrip_blocks': True,
      'trim_blocks': True,
    }

  def GetGlobals(self):
    return {
      'namespace': self.module.namespace,
      'module': self.module,
    }
