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

import _env  # pylint: disable=unused-import
from idl_definitions import IdlTypedef
from idl_types import IdlPromiseType
from idl_types import IdlSequenceType
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
from v8_attributes import is_constructor_attribute
from v8_interface import method_overloads_by_name


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


def is_any_type(idl_type):
  return idl_type.name == 'Any'


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


def is_promise_type(idl_type):
  return isinstance(idl_type, IdlPromiseType)


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'
  if idl_type.is_enum:
    return convert_to_cobalt_enumeration_value(idl_type, idl_literal.value)
  return str(idl_literal)


def get_dictionary_default_value(idl_type, idl_literal, name):
  """Mapping to cobalt value filtering for dictionary acceptable values."""
  if is_any_type(idl_type) and not idl_literal.is_null:
    raise ValueError('Unsupported default value in dictionary: '
                     '\'%s %s = %s\'. Only null default is supported.' %
                     (idl_type, name, idl_literal))
  return idl_literal_to_cobalt_literal(idl_type, idl_literal)


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_string_type_to_cobalt(idl_type):
  """Map IDL string type to C++ type."""
  type_map = {
      'ByteString': 'std::vector<uint8_t>',
      'DOMString': 'std::string',
      'String': 'std::string',
      'StringOrNull': 'std::string',
      'USVString': 'std::string',
  }
  assert idl_type.is_string_type, 'Expected string type.'
  return type_map[idl_type.name]


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) or
      is_any_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 get_optional_arguments(arguments):
  """Create optional arguments list."""
  return [argument for argument in arguments if argument['is_optional']]


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_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 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 get_conversion_flags(idl_type, extended_attributes):
  """Build an expression setting a bitmask of flags used for conversion."""
  assert not isinstance(idl_type, IdlTypedef)
  flags = []
  # 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 extended_attributes.get('TreatNullAs', '') == 'EmptyString':
      flags.append('kConversionFlagTreatNullAsEmptyString')
    elif extended_attributes.get('TreatUndefinedAs', '') == 'EmptyString':
      flags.append('kConversionFlagTreatUndefinedAsEmptyString')

  if extended_attributes.has_key('Clamp'):
    flags.append('kConversionFlagClamped')

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


class ContextBuilder(object):
  """Build jinja2 contexts (python dicts) for use in bindings generation."""

  def __init__(self, info_provider):
    self.info_provider = info_provider

  def resolve_typedef(self, idl_type):
    idl_type = idl_type.resolve_typedefs(self.info_provider.typedefs)
    if isinstance(idl_type, IdlTypedef):
      idl_type = idl_type.idl_type
    return idl_type

  def idl_sequence_type_to_cobalt(self, 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 = self.idl_type_to_cobalt_type(
        self.resolve_typedef(element_idl_type))
    return '::cobalt::script::Sequence< %s >' % element_cobalt_type

  def idl_union_type_to_cobalt(self, 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:
      member = self.resolve_typedef(member)
      if member.is_nullable:
        member = member.inner_type

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

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

  def idl_type_to_cobalt_type(self, idl_type):
    """Map IDL type to C++ type."""
    assert not isinstance(idl_type, IdlTypedef)
    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 = idl_string_type_to_cobalt(idl_type)
    elif idl_type.is_callback_interface:
      cobalt_type = '::cobalt::script::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 = self.idl_union_type_to_cobalt(idl_type)
    elif idl_type.is_enum:
      cobalt_type = idl_type.name
    elif is_sequence_type(idl_type):
      cobalt_type = self.idl_sequence_type_to_cobalt(idl_type)
    elif idl_type.name == 'void':
      cobalt_type = 'void'
    elif is_object_type(idl_type):
      cobalt_type = '::cobalt::script::OpaqueHandle'
    elif is_any_type(idl_type):
      cobalt_type = '::cobalt::script::ValueHandle'
    elif idl_type.is_dictionary:
      cobalt_type = get_interface_name(idl_type)
    elif is_promise_type(idl_type):
      cobalt_type = '::cobalt::script::NativePromise'

    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(self, interface, typed_object):
    """Map type of IDL TypedObject to C++ type."""
    idl_type = self.resolve_typedef(typed_object.idl_type)
    if idl_type.is_callback_function:
      cobalt_type = interface.name + '::' + get_interface_name(idl_type)
    else:
      cobalt_type = self.idl_type_to_cobalt_type(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(self, interface, typed_object):
    """Map type of IDL TypedObject to C++ type that is a function argument."""
    base_type = self.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 is_any_type(idl_type):
      return 'const ::cobalt::script::ScriptValue<%s>*' % base_type
    if idl_type.is_string_type or idl_type.is_interface_type:
      return 'const %s&' % base_type
    return base_type

  def argument_context(self, interface, argument):
    """Create template values for method/constructor arguments."""
    return {
        'idl_type_object':
            argument.idl_type,
        'name':
            argument.name,
        'type':
            self.typed_object_to_cobalt_type(interface, argument),
        'arg_type':
            self.typed_object_to_arg_type(interface, argument),
        'conversion_flags':
            get_conversion_flags(
                self.resolve_typedef(argument.idl_type),
                argument.extended_attributes),
        '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 partial_context(self, interface, operation):
    """Create partial template values for generating bindings."""
    arguments = [
        self.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(self, 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(self.partial_context(interface, constructor))
    return context

  def method_context(self, interface, operation):
    """Create template values for generating method bindings."""
    context = {
        'idl_name':
            operation.name,
        'name':
            capitalize_function_name(operation.name),
        'type':
            self.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(self.partial_context(interface, operation))
    return context

  def stringifier_context(self, 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(self, 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'] = self.typed_object_to_cobalt_type(interface, operation)
    else:
      value_argument = operation.arguments[1]
      context['type'] = self.typed_object_to_cobalt_type(
          interface, value_argument)
      context['conversion_flags'] = get_conversion_flags(
          self.resolve_typedef(value_argument.idl_type),
          value_argument.extended_attributes)

    return context

  def attribute_context(self, interface, attribute, definitions):
    """Create template values for attribute bindings."""
    cobalt_name = attribute.extended_attributes.get('ImplementedAs',
                                                    convert_to_cobalt_name(
                                                        attribute.name))
    context = {
        'idl_name':
            attribute.name,
        'getter_function_name':
            cobalt_name,
        'setter_function_name':
            'set_' + cobalt_name,
        'type':
            self.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(
                self.resolve_typedef(attribute.idl_type),
                attribute.extended_attributes),
        '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'] = self.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(self, enumeration):
    """Create template values for IDL enumeration type bindings."""
    return {
        'enumeration_name':
            enumeration.name,
        'value_pairs': [(
            convert_to_cobalt_enumeration_value(enumeration.name, value),
            value,
        ) for value in enumeration.values],
    }

  def constant_context(self, 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(self, 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 = [
        self.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(self, 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 = [
        self.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]

  def get_dictionary_member_context(self, dictionary, dictionary_member):
    """Returns a jinja context for a dictionary member.

    Arguments:
        dictionary: An IdlDictionary object
        dictionary_member: An IdlDictionaryMember object.
    Returns:
      dictionary_member_context (dict)
    """
    return {
        'idl_type_object':
            dictionary_member.idl_type,
        'name':
            convert_to_cobalt_name(dictionary_member.name),
        'is_script_value':
            is_any_type(dictionary_member.idl_type),
        'idl_name':
            dictionary_member.name,
        'type':
            self.typed_object_to_cobalt_type(dictionary, dictionary_member),
        'arg_type':
            self.typed_object_to_arg_type(dictionary, dictionary_member),
        'conversion_flags':
            get_conversion_flags(
                self.resolve_typedef(dictionary_member.idl_type),
                dictionary_member.extended_attributes),
        'default_value':
            get_dictionary_default_value(dictionary_member.idl_type,
                                         dictionary_member.default_value,
                                         dictionary_member.name)
            if dictionary_member.default_value else None,
    }
