# Copyright 2015 Google Inc. All Rights Reserved.
# coding=utf-8
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Create contexts to be used by Jinja template generation.

Extract the relevant information from the IdlParser objects and store them in
dicts that will be used by Jinja in JS bindings generation.
"""

from bindings.scripts.idl_types import IdlSequenceType
from bindings.scripts.v8_attributes import is_constructor_attribute
from bindings.scripts.v8_interface import method_overloads_by_name
from name_conversion import capitalize_function_name
from name_conversion import convert_to_cobalt_constant_name
from name_conversion import convert_to_cobalt_enumeration_value
from name_conversion import convert_to_cobalt_name
from name_conversion import get_interface_name
from overload_context import get_overload_contexts


def idl_primitive_type_to_cobalt(idl_type):
  """Map IDL primitive type to C++ type."""
  type_map = {
      'boolean': 'bool',
      'byte': 'int8_t',
      'octet': 'uint8_t',
      'short': 'int16_t',
      'unsigned short': 'uint16_t',
      'long': 'int32_t',
      'long long': 'int64_t',
      'unsigned long': 'uint32_t',
      'unsigned long long': 'uint64_t',
      'float': 'float',
      'unrestricted float': 'float',
      'double': 'double',
      'unrestricted double': 'double',
  }
  assert idl_type.is_primitive_type, 'Expected primitive type.'
  return type_map[idl_type.base_type]


def idl_sequence_type_to_cobalt(idl_type):
  """Map IDL sequence type to C++ sequence type implementation."""
  assert is_sequence_type(idl_type), 'Expected sequence type.'
  element_idl_type = idl_type.element_type
  assert not is_object_type(element_idl_type), 'Object type not supported.'
  assert (not element_idl_type.is_callback_function and
          not idl_type.is_callback_interface), 'Callback types not supported.'
  element_cobalt_type = idl_type_to_cobalt_type(element_idl_type)
  return 'script::Sequence< %s >' % element_cobalt_type


def idl_union_type_to_cobalt(idl_type):
  """Map IDL union type to C++ union type implementation."""
  # Flatten the union type. Order matters for our implementation.
  assert idl_type.is_union_type, 'Expected union type.'
  flattened_types = []
  for member in idl_type.member_types:
    if member.is_nullable:
      member = member.inner_type

    if member.is_union_type:
      flattened_types.extend(idl_union_type_to_cobalt(member))
    else:
      flattened_types.append(member)

  cobalt_types = [idl_type_to_cobalt_type(t) for t in flattened_types]
  return 'script::UnionType%d<%s >' % (len(cobalt_types),
                                       ', '.join(cobalt_types))


def idl_union_type_has_nullable_member(idl_type):
  """Return True iff the idl_type is a union with a nullable member."""
  assert idl_type.is_union_type, 'Expected union type.'
  for member in idl_type.member_types:
    if member.is_nullable:
      return True
    elif member.is_union_type and idl_union_type_has_nullable_member(member):
      return True
  return False


def cobalt_type_is_optional(idl_type):
  """Return True iff the idl_type should be wrapped by a base::optional<>.

  Returns:
    (bool): Whether the cobalt type should be wrapped in base::optional<>.
  Args:
    idl_type: An idl_types.IdlType object.

  The Cobalt type for interfaces and callback functions are scoped_refptr, so
  they can already be assigned a NULL value. Other types, such as primitives,
  strings, and unions, need to be wrapped by base::optional<>, in which case
  the IDL null value will map to base::nullopt_t.
  """

  # These never need base::optional<>
  if (idl_type.is_interface_type or idl_type.is_callback_function or
      idl_type.is_callback_interface or is_object_type(idl_type)):
    return False

  # We consider a union type to be nullable if either the entire union is
  # nullable, or one of its member types are.
  return (idl_type.is_nullable or
          (idl_type.is_union_type and
           (idl_union_type_has_nullable_member(idl_type))))


def is_object_type(idl_type):
  return str(idl_type) == 'object'


def is_sequence_type(idl_type):
  return isinstance(idl_type, IdlSequenceType)


def idl_type_to_cobalt_type(idl_type):
  """Map IDL type to C++ type."""
  cobalt_type = None
  if idl_type.is_primitive_type:
    cobalt_type = idl_primitive_type_to_cobalt(idl_type)
  elif idl_type.is_string_type:
    cobalt_type = 'std::string'
  elif idl_type.is_callback_interface:
    cobalt_type = 'CallbackInterfaceTraits<%s >' % get_interface_name(idl_type)
  elif idl_type.is_interface_type:
    cobalt_type = 'scoped_refptr<%s>' % get_interface_name(idl_type)
  elif idl_type.is_union_type:
    cobalt_type = idl_union_type_to_cobalt(idl_type)
  elif is_sequence_type(idl_type):
    cobalt_type = idl_sequence_type_to_cobalt(idl_type)
  elif idl_type.name == 'void':
    cobalt_type = 'void'
  elif is_object_type(idl_type):
    cobalt_type = 'OpaqueHandle'

  assert cobalt_type, 'Unsupported idl_type %s' % idl_type

  if cobalt_type_is_optional(idl_type):
    cobalt_type = 'base::optional<%s >' % cobalt_type

  return cobalt_type


def typed_object_to_cobalt_type(interface, typed_object):
  """Map type of IDL TypedObject to C++ type."""
  if typed_object.idl_type.is_callback_function:
    cobalt_type = interface.name + '::' + get_interface_name(
        typed_object.idl_type)
  elif typed_object.idl_type.is_enum:
    cobalt_type = '%s::%s' % (interface.name,
                              get_interface_name(typed_object.idl_type))
  else:
    cobalt_type = idl_type_to_cobalt_type(typed_object.idl_type)
  if getattr(typed_object, 'is_variadic', False):
    cobalt_type = 'std::vector<%s>' % cobalt_type
  return cobalt_type


def typed_object_to_arg_type(interface, typed_object):
  """Map type of IDL TypedObject to C++ type that is a function argument."""
  base_type = typed_object_to_cobalt_type(interface, typed_object)

  idl_type = typed_object.idl_type
  if (idl_type.is_callback_function or idl_type.is_object_type or
      idl_type.is_callback_interface):
    return base_type + '*'
  if idl_type.is_string_type or idl_type.is_interface_type:
    return 'const %s&' % base_type
  return base_type


def idl_literal_to_cobalt_literal(idl_type, idl_literal):
  """Map IDL literal to the corresponding cobalt value."""
  if idl_literal.is_null and not idl_type.is_interface_type:
    return 'base::nullopt'
  return str(idl_literal)


def get_conversion_flags(typed_object):
  """Build an expression setting a bitmask of flags used for conversion."""
  flags = []
  idl_type = typed_object.idl_type
  # Flags must correspond to the enumeration in
  # scripts/javascriptcore/conversion_helpers.h
  if (idl_type.is_numeric_type and not idl_type.is_integer_type and
      not idl_type.base_type.startswith('unrestricted ')):
    flags.append('kConversionFlagRestricted')
  if idl_type.is_nullable and not cobalt_type_is_optional(idl_type.inner_type):
    # Other types use base::optional<> so there is no need for a flag to check
    # if null values are allowed.
    flags.append('kConversionFlagNullable')
  if idl_type.is_string_type:
    if typed_object.extended_attributes.get('TreatNullAs', '') == 'EmptyString':
      flags.append('kConversionFlagTreatNullAsEmptyString')
    elif (typed_object.extended_attributes.get('TreatUndefinedAs', '') ==
          'EmptyString'):
      flags.append('kConversionFlagTreatUndefinedAsEmptyString')

  if flags:
    return '(%s)' % ' | '.join(flags)
  else:
    return 'kNoConversionFlags'


def argument_context(interface, argument):
  """Create template values for method/constructor arguments."""
  return {
      'idl_type_object': argument.idl_type,
      'name': argument.name,
      'type': typed_object_to_cobalt_type(interface, argument),
      'arg_type': typed_object_to_arg_type(interface, argument),
      'conversion_flags': get_conversion_flags(argument),
      'is_optional': argument.is_optional,
      'is_variadic': argument.is_variadic,
      'default_value': idl_literal_to_cobalt_literal(argument.idl_type,
                                                     argument.default_value) if
                       argument.default_value else None,
  }


def get_non_optional_arguments(arguments):
  """Create non optional arguments list."""
  return [argument for argument in arguments
          if not argument['is_optional'] and not argument['is_variadic']]


def get_optional_arguments(arguments):
  """Create optional arguments list."""
  return [argument for argument in arguments if argument['is_optional']]


def get_num_default_arguments(optional_arguments):
  """Return the number of default arguments."""
  num_default_arguments = 0

  for argument in optional_arguments:
    if argument['default_value'] is not None:
      num_default_arguments += 1

  return num_default_arguments


def get_variadic_argument(arguments):
  """Return the variadic argument."""
  length = len(arguments)

  if length > 0 and arguments[length - 1]['is_variadic']:
    return arguments[length - 1]
  else:
    return []


def partial_context(interface, operation):
  """Create partial template values for generating bindings."""
  arguments = [argument_context(interface, a) for a in operation.arguments]
  optional_arguments = get_optional_arguments(arguments)
  num_default_arguments = get_num_default_arguments(optional_arguments)
  return {
      'arguments': arguments,
      'non_optional_arguments': get_non_optional_arguments(arguments),
      'optional_arguments': optional_arguments,
      'num_default_arguments': num_default_arguments,
      'variadic_argument': get_variadic_argument(arguments),
      'has_non_default_optional_arguments': len(optional_arguments) >
                                            num_default_arguments,
  }


def constructor_context(interface, constructor):
  """Create template values for generating constructor bindings."""
  context = {
      'call_with': interface.extended_attributes.get('ConstructorCallWith',
                                                     None),
      'raises_exception': (interface.extended_attributes.get(
          'RaisesException', None) == 'Constructor'),
  }

  context.update(partial_context(interface, constructor))
  return context


def method_context(interface, operation):
  """Create template values for generating method bindings."""
  context = {
      'idl_name': operation.name,
      'name': capitalize_function_name(operation.name),
      'type': typed_object_to_cobalt_type(interface, operation),
      'is_static': operation.is_static,
      'call_with': operation.extended_attributes.get('CallWith', None),
      'raises_exception':
          operation.extended_attributes.has_key('RaisesException'),
      'conditional': operation.extended_attributes.get('Conditional', None),
      'unsupported': 'NotSupported' in operation.extended_attributes,
  }

  context.update(partial_context(interface, operation))
  return context


def stringifier_context(interface):
  """Create template values for generating stringifier."""
  if not interface.stringifier:
    return None
  if interface.stringifier.attribute:
    cobalt_name = convert_to_cobalt_name(interface.stringifier.attribute.name)
  elif interface.stringifier.operation:
    cobalt_name = capitalize_function_name(interface.stringifier.operation.name)
  else:
    cobalt_name = 'AnonymousStringifier'
  return {'name': cobalt_name,}


def special_method_context(interface, operation):
  """Create template values for getter and setter bindings."""
  if not operation or not operation.specials:
    return None

  assert operation.arguments
  is_indexed = str(operation.arguments[0].idl_type) == 'unsigned long'
  is_named = str(operation.arguments[0].idl_type) == 'DOMString'

  assert len(operation.specials) == 1
  special_type = operation.specials[0]
  assert special_type in ('getter', 'setter', 'deleter')

  function_suffix = {
      'getter': 'Getter',
      'setter': 'Setter',
      'deleter': 'Deleter',
  }

  if operation.name:
    cobalt_name = capitalize_function_name(operation.name)
  elif is_indexed:
    cobalt_name = 'AnonymousIndexed%s' % function_suffix[special_type]
  else:
    assert is_named
    cobalt_name = 'AnonymousNamed%s' % function_suffix[special_type]

  context = {
      'name': cobalt_name,
      'raises_exception':
          operation.extended_attributes.has_key('RaisesException'),
  }

  if special_type in ('getter', 'deleter'):
    context['type'] = typed_object_to_cobalt_type(interface, operation)
  else:
    context['type'] = typed_object_to_cobalt_type(interface,
                                                  operation.arguments[1])
    context['conversion_flags'] = get_conversion_flags(operation.arguments[1])

  return context


def attribute_context(interface, attribute, definitions):
  """Create template values for attribute bindings."""
  context = {
      'idl_name': attribute.name,
      'getter_function_name': convert_to_cobalt_name(attribute.name),
      'setter_function_name': 'set_' + convert_to_cobalt_name(attribute.name),
      'type': typed_object_to_cobalt_type(interface, attribute),
      'is_static': attribute.is_static,
      'is_read_only': attribute.is_read_only,
      'call_with': attribute.extended_attributes.get('CallWith', None),
      'raises_exception':
          attribute.extended_attributes.has_key('RaisesException'),
      'conversion_flags': get_conversion_flags(attribute),
      'conditional': attribute.extended_attributes.get('Conditional', None),
      'unsupported': 'NotSupported' in attribute.extended_attributes,
  }
  forwarded_attribute_name = attribute.extended_attributes.get('PutForwards')
  if forwarded_attribute_name:
    assert attribute.idl_type.is_interface_type, (
        'PutForwards must be declared on a property of interface type.')
    assert attribute.is_read_only, (
        'PutForwards must be on a readonly attribute.')
    forwarded_interface = definitions.interfaces[get_interface_name(
        attribute.idl_type)]
    matching_attributes = [a for a in forwarded_interface.attributes
                           if a.name == forwarded_attribute_name]
    assert len(matching_attributes) == 1
    context['put_forwards'] = attribute_context(forwarded_interface,
                                                matching_attributes[0],
                                                definitions)
  context['has_setter'] = not attribute.is_read_only or forwarded_attribute_name
  if is_constructor_attribute(attribute):
    context['is_constructor_attribute'] = True
    context['interface_name'] = get_interface_name(attribute.idl_type)
    # Blink's IDL parser uses the convention that attributes ending with
    # 'ConstructorConstructor' are for Named Constructors.
    context['is_named_constructor_attribute'] = (
        attribute.idl_type.name.endswith('ConstructorConstructor'))
  return context


def enumeration_context(enumeration):
  """Create template values for IDL enumeration type bindings."""
  return {
      'name': enumeration.name,
      'value_pairs': [(convert_to_cobalt_enumeration_value(value),
                       value,) for value in enumeration.values],
  }


def constant_context(constant):
  """Create template values for IDL constant bindings."""
  assert constant.idl_type.is_primitive_type, ('Only primitive types can be '
                                               'declared as constants.')
  return {
      'name': convert_to_cobalt_constant_name(constant.name),
      'idl_name': constant.name,
      'value': constant.value,
      'can_use_compile_assert': constant.idl_type.is_integer_type,
      'unsupported': 'NotSupported' in constant.extended_attributes,
  }


def get_method_contexts(expression_generator, interface):
  """Return a list of overload contexts for generating method bindings.

  The 'overloads' key of the overload_contexts will be the list of
  method_contexts that are overloaded to this name. In the case that
  a function is not overloaded, the length of this list will be one.

  Arguments:
      expression_generator: An ExpressionGenerator object.
      interface: an IdlInterface object
  Returns:
      [overload_contexts]
  """

  # Get the method contexts for all operations.
  methods = [
      method_context(interface, operation) for operation in interface.operations
      if operation.name
  ]

  # Create overload sets for static and non-static methods seperately.
  # Each item in the list is a pair of (name, [method_contexts]) where for
  # each method_context m in the list, m['name'] == name.
  static_method_overloads = method_overloads_by_name([m for m in methods
                                                      if m['is_static']])
  non_static_method_overloads = method_overloads_by_name(
      [m for m in methods if not m['is_static']])
  static_overload_contexts = get_overload_contexts(
      expression_generator, [contexts
                             for _, contexts in static_method_overloads])
  non_static_overload_contexts = get_overload_contexts(
      expression_generator, [contexts
                             for _, contexts in non_static_method_overloads])

  # Set is_static on each of these appropriately.
  for context in static_overload_contexts:
    context['is_static'] = True
  for context in non_static_overload_contexts:
    context['is_static'] = False

  # Append the lists and add the idl_name of the operation to the
  # top-level overload context.
  overload_contexts = static_overload_contexts + non_static_overload_contexts
  for context in overload_contexts:
    context['idl_name'] = context['overloads'][0]['idl_name']
    context['conditional'] = context['overloads'][0]['conditional']
    context['unsupported'] = context['overloads'][0]['unsupported']
    for overload in context['overloads']:
      assert context['conditional'] == overload['conditional'], (
          'All overloads must have the same conditional.')
    for overload in context['overloads']:
      assert context['unsupported'] == overload['unsupported'], (
          'All overloads must have the value for NotSupported.')

  return overload_contexts


def get_constructor_context(expression_generator, interface):
  """Return an overload_context for generating constructor bindings.

  The 'overloads' key for the overloads_context will be a list of
  constructor_contexts representing all constructor overloads. In the
  case that the constructor is not overloaded, the length of this list
  will be one.
  The overload_context also has a 'length' key which can be used to
  specify the 'length' property for the constructor.

  Arguments:
      expression_generator: An ExpressionGenerator object.
      interface: An IdlInterface object.
  Returns:
      overload_context
  """

  constructors = [
      constructor_context(interface, constructor)
      for constructor in interface.constructors
  ]
  if not constructors:
    return None
  else:
    overload_contexts = get_overload_contexts(expression_generator,
                                              [constructors])
    assert len(overload_contexts) == 1, (
        'Expected exactly one overload context for constructor.')
    return overload_contexts[0]
