#!/usr/bin/python
# Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.
"""This module provides shared functionality for the system to generate
dart:html APIs from the IDL database."""

import emitter
from generator import AnalyzeOperation, ConstantOutputOrder, \
    DartDomNameOfAttribute, FindMatchingAttribute, IsPureInterface, \
    TypeOrNothing, ConvertToFuture, GetCallbackInfo
from copy import deepcopy
from htmlrenamer import convert_to_future_members, custom_html_constructors, \
    GetDDC_Extension, keep_overloaded_members, overloaded_and_renamed,\
    private_html_members, renamed_html_members, renamed_overloads, \
    removed_html_members
from generator import TypeOrVar
import logging
import monitored
import sys

_logger = logging.getLogger('htmldartgenerator')

# Types that are accessible cross-frame in a limited fashion.
# In these cases, the base type (e.g., WindowBase) provides restricted access
# while the subtype (e.g., Window) provides full access to the
# corresponding objects if there are from the same frame.
_secure_base_types = {
    'Window': 'WindowBase',
    'Location': 'LocationBase',
    'History': 'HistoryBase',
}

_custom_factories = [
    'Notification',
    'EventSource',
]


class HtmlDartGenerator(object):

    def __init__(self, interface, options, dart_use_blink, logger):
        self._dart_use_blink = dart_use_blink
        self._database = options.database
        self._interface = interface
        self._type_registry = options.type_registry
        self._interface_type_info = self._type_registry.TypeInfo(
            self._interface.id)
        self._renamer = options.renamer
        self._metadata = options.metadata
        self._library_name = self._renamer.GetLibraryName(self._interface)
        _logger.setLevel(logger.level)

    def EmitSupportCheck(self):
        if self.HasSupportCheck():
            check = self.GetSupportCheck()
            if type(check) != tuple:
                signature = 'get supported'
            else:
                signature = check[0]
                check = check[1]
            self._members_emitter.Emit(
                '\n'
                '  /// Checks if this type is supported on the current platform.\n'
                '  static bool $SIGNATURE => $SUPPORT_CHECK;\n',
                SIGNATURE=signature,
                SUPPORT_CHECK=check)

    def EmitEventGetter(self, events_class_name):
        self._members_emitter.Emit(
            "EventTarget.removeEventListener, EventTarget.dispatchEvent')"
            "\n  @deprecated"
            "\n  $TYPE get on =>\n    new $TYPE(this);\n",
            TYPE=events_class_name)

    def AddMembers(self, interface, declare_only=False, dart_js_interop=False):
        if self._interface.id == 'WebGLRenderingContextBase' or self._interface.id == 'WebGL2RenderingContextBase' or \
            self._interface.id == 'WebGLDrawBuffers':
            # Constants in classes WebGLRenderingContextBase, WebGL2RenderingContext, WebGLDrawBuffers are consolidated into
            # one synthesized class (WebGL).
            self._gl_constants.extend(interface.constants)
        else:
            for const in sorted(interface.constants, ConstantOutputOrder):
                self.AddConstant(const)

        for attr in sorted(interface.attributes, ConstantOutputOrder):
            if attr.type.id != 'EventHandler' and attr.type.id != 'EventListener':
                self.AddAttribute(attr, declare_only)

        # The implementation should define an indexer if the interface directly
        # extends List.
        element_type = None
        requires_indexer = False
        if self._interface_type_info.list_item_type():
            self.AddIndexer(self._interface_type_info.list_item_type(),
                            self._interface_type_info.list_item_type_nullable())
        else:
            for parent in self._database.Hierarchy(self._interface):
                if parent == self._interface:
                    continue
                parent_type_info = self._type_registry.TypeInfo(parent.id)
                if parent_type_info.list_item_type():
                    self.AmendIndexer(parent_type_info.list_item_type())
                    break

        # Group overloaded operations by name.
        self._AddRenamedOverloads(interface)
        operationsByName = self._OperationsByName(interface)
        if self.OmitOperationOverrides():
            self._RemoveShadowingOperationsWithSameSignature(
                operationsByName, interface)

        # Generate operations.
        for id in sorted(operationsByName.keys()):
            operations = operationsByName[id]
            info = AnalyzeOperation(interface, operations)
            info.nnbd = self._nnbd
            self.AddOperation(info, declare_only, dart_js_interop)
            if ('%s.%s' % (interface.id,
                           info.declared_name) in convert_to_future_members):
                self.AddOperation(ConvertToFuture(info), declare_only)

    def AddSecondaryMembers(self, interface):
        secondary_parents = self._database.TransitiveSecondaryParents(
            interface, not self._dart_use_blink)
        remove_duplicate_parents = list(set(secondary_parents))
        if len(secondary_parents) != len(remove_duplicate_parents):
            secondary_parents = remove_duplicate_parents
            parent_list = ", ".join(
                ["  %s" % (parent.id) for parent in secondary_parents])
            _logger.warn('Interface %s has duplicate parent interfaces %s - ' \
                         'ignoring duplicates. Please file a bug with the dart:html team.' % (interface.id, parent_list))

        for parent_interface in sorted(secondary_parents):
            if isinstance(parent_interface, str):
                continue

            for attr in sorted(parent_interface.attributes,
                               ConstantOutputOrder):
                if not FindMatchingAttribute(interface, attr):
                    if attr.type.id != 'EventHandler':
                        self.SecondaryContext(parent_interface)
                        self.AddAttribute(attr)

            # Group overloaded operations by name.
            operationsByName = self._OperationsByName(parent_interface)

            if self.OmitOperationOverrides():
                self._RemoveShadowingOperationsWithSameSignature(
                    operationsByName, interface)

            # Generate operations.
            for id in sorted(operationsByName.keys()):
                if not any(op.id == id for op in interface.operations):
                    operations = operationsByName[id]
                    info = AnalyzeOperation(interface, operations)
                    self.SecondaryContext(parent_interface)
                    self.AddOperation(info)

    def _RemoveShadowingOperationsWithSameSignature(self, operationsByName,
                                                    interface):
        if not interface.parents:
            return

        parent_name = interface.parents[0].type.id
        parent = self._database.GetInterface(parent_name)
        if parent == self._interface or parent == interface:
            return

        # Never remove operations that are added as a result of an implements they
        # are pure interfaces (mixins to this interface).
        if (IsPureInterface(parent_name, self._database)):
            return

        for operation in parent.operations:
            if operation.id in operationsByName:
                operations = operationsByName[operation.id]
                for existing_operation in operations:
                    if existing_operation.SameSignatureAs(operation):
                        del operationsByName[operation.id]

    def _AddRenamedOverloads(self, interface):
        """The IDL has a number of functions with the same name but that accept
    different types. This is fine for JavaScript, but results in vague type
    signatures for Dart. We rename some of these (by adding a new identical
    operation with a different DartName), but leave the original version as
    well in some cases."""
        potential_added_operations = set()
        operations_by_name = self._OperationsByName(interface)
        already_renamed = [
            operation.ext_attrs['DartName']
            if 'DartName' in operation.ext_attrs else ''
            for operation in interface.operations
        ]

        added_operations = []
        for operation in interface.operations:
            full_operation_str = self._GetStringRepresentation(
                interface, operation)
            if (full_operation_str in renamed_overloads and
                    renamed_overloads[full_operation_str] not in already_renamed
               ):
                if '%s.%s' % (interface.id,
                              operation.id) in overloaded_and_renamed:
                    cloned_operation = deepcopy(operation)
                    cloned_operation.ext_attrs['DartName'] = renamed_overloads[
                        full_operation_str]
                    added_operations.append(cloned_operation)
                else:
                    dart_name = renamed_overloads[full_operation_str]
                    if not dart_name:
                        continue

                    operation.ext_attrs['DartName'] = dart_name
                    potential_added_operations.add(operation.id)
            self._EnsureNoMultipleTypeSignatures(interface, operation,
                                                 operations_by_name)
        interface.operations += added_operations
        self._AddDesiredOverloadedOperations(potential_added_operations,
                                             interface, operations_by_name)

    def _AddDesiredOverloadedOperations(self, potential_added_operations,
                                        interface, original_operations_by_name):
        """For some cases we desire to keep the overloaded version in dart, for
    simplicity of API, and explain the parameters accepted in documentation."""
        updated_operations_by_name = self._OperationsByName(interface)
        for operation_id in potential_added_operations:
            if (operation_id not in updated_operations_by_name and '%s.%s' %
                (interface.id, operation_id) in keep_overloaded_members):
                for operation in original_operations_by_name[operation_id]:
                    cloned_operation = deepcopy(operation)
                    cloned_operation.ext_attrs['DartName'] = operation_id
                    interface.operations.append(cloned_operation)

    def _EnsureNoMultipleTypeSignatures(self, interface, operation,
                                        operations_by_name):
        """Make sure that there is now at most one operation with a particular
    operation.id. If not, stop library generation, and throw an error, requiring
    programmer input about the best name change before proceeding."""
        operation_str = '%s.%s' % (interface.id, operation.id)

        if (operation.id in operations_by_name and
                len(operations_by_name[operation.id]) > 1 and len(
                    filter(lambda overload: overload.startswith(operation_str),
                           renamed_overloads.keys())) == 0 and
                operation_str not in keep_overloaded_members and
                operation_str not in overloaded_and_renamed and
                operation_str not in renamed_html_members and
                operation_str not in private_html_members and
                operation_str not in removed_html_members and
                operation.id != '__getter__' and
                operation.id != '__setter__' and operation.id != '__delete__'):
            _logger.warn(
                'Multiple type signatures for %s.%s. Please file a bug with'
                ' the dart:html team to determine if one of these functions should be'
                ' renamed.' % (interface.id, operation.id))

    def _GetStringRepresentation(self, interface, operation):
        """Given an IDLOperation, return a object-independent representation of the
    operations's signature."""
        return '%s.%s(%s)' % (interface.id, operation.id, ', '.join(
            ['%s %s' % (arg.type.id, arg.id) for arg in operation.arguments]))

    def _OperationsByName(self, interface):
        operationsByName = {}
        for operation in interface.operations:
            name = operation.ext_attrs.get('DartName', operation.id)
            operationsByName.setdefault(name, []).append(operation)
        return operationsByName

    def OmitOperationOverrides(self):
        return False

    def AddConstant(self, constant):
        const_name = self._renamer.RenameMember(
            self._interface.id,
            constant,
            constant.id,
            'get:',
            dartify_name=False)
        if not const_name:
            return

        annotations = self._metadata.GetFormattedMetadata(
            self._library_name, self._interface, constant.id, '  ')

        type = TypeOrNothing(self._DartType(constant.type.id), constant.type.id)
        self._members_emitter.Emit(
            '\n  $(ANNOTATIONS)static const $TYPE$NAME = $VALUE;\n',
            ANNOTATIONS=annotations,
            NAME=const_name,
            TYPE=type,
            VALUE=constant.value)

    def AddAttribute(self, attribute, declare_only=False):
        """ Adds an attribute to the generated class.
    Arguments:
      attribute - The attribute which is to be added.
      declare_only- True if the attribute should be declared as an abstract
        member and not include invocation code.
    """
        dom_name = DartDomNameOfAttribute(attribute)
        attr_name = self._renamer.RenameMember(self._interface.id, attribute,
                                               dom_name, 'get:')
        if not attr_name:
            return

        html_setter_name = self._renamer.RenameMember(
            self._interface.id, attribute, dom_name, 'set:')
        read_only = (attribute.is_read_only or
                     'Replaceable' in attribute.ext_attrs or
                     not html_setter_name)

        # We don't yet handle inconsistent renames of the getter and setter yet.
        assert (not html_setter_name or attr_name == html_setter_name)

        # any is assumed to be nullable
        if attribute.type.id == 'any':
            attribute.type.nullable = True

        if declare_only:
            self.DeclareAttribute(attribute,
                                  self.SecureOutputType(attribute.type.id,
                                    nullable=attribute.type.nullable),
                                  attr_name, read_only)
        else:
            self.EmitAttribute(attribute, attr_name, read_only)

    def AddOperation(self, info, declare_only=False, dart_js_interop=False):
        # TODO(terry): Hack window has 2 overloaded getter one returns Window and
        #              and other object (we'll always return Window)?
        if self._interface.id == "Window" and info.name == '__getter__':
            info.operations[1].type = info.operations[0].type
        """ Adds an operation to the generated class.
    Arguments:
      info - The operation info of the operation to be added.
      declare_only- True if the operation should be declared as an abstract
        member and not include invocation code.
    """
        # FIXME: When we pass in operations[0] below, we're assuming all
        # overloaded operations have the same security attributes.  This
        # is currently true, but we should consider filtering earlier or
        # merging the relevant data into info itself.
        method_name = self._renamer.RenameMember(
            self._interface.id, info.operations[0], info.name, 'call:')
        if not method_name:
            if info.name == 'item':
                # FIXME: item should be renamed to operator[], not removed.
                self.EmitOperation(info, '_item')
            return

        if declare_only:
            self.DeclareOperation(info,
                                  self.SecureOutputType(info.type_name,
                                      nullable=info.type_nullable),
                                  method_name)
        else:
            self.EmitOperation(info, method_name, dart_js_interop)

    def _GenerateOverloadDispatcher(
            self,
            info,
            signatures,
            is_void,
            declaration,
            generate_call,
            is_optional,
            emitter,
            can_omit_type_check=lambda type, pos: False):

        parameter_names = [p.name for p in info.param_infos]
        number_of_required_in_dart = info.NumberOfRequiredInDart()

        body_emitter = emitter.Emit('\n'
                                    '  $DECLARATION {\n'
                                    '$!BODY'
                                    '  }\n',
                                    DECLARATION=declaration)

        version = [0]

        def GenerateCall(signature_index, argument_count, checks):
            if checks:
                (stmts_emitter, call_emitter) = body_emitter.Emit(
                    '    if ($CHECKS) {\n$!STMTS$!CALL    }\n',
                    INDENT='      ',
                    CHECKS=' && '.join(checks))
            else:
                (stmts_emitter, call_emitter) = body_emitter.Emit(
                    '$!STMTS$!CALL', INDENT='    ')

            if is_void:
                call_emitter = call_emitter.Emit(
                    '$(INDENT)$!CALL;\n$(INDENT)return;\n')
            else:
                call_emitter = call_emitter.Emit('$(INDENT)return $!CALL;\n')

            version[0] += 1
            generate_call(stmts_emitter, call_emitter, version[0],
                          signature_index, argument_count)

        def IsTypeChecking(interface_argument):
            return 'LegacyInterfaceTypeChecking' in interface_argument.ext_attrs or \
            self._database.HasInterface(interface_argument.id)

        def GenerateChecksAndCall(signature_index, argument_count):
            checks = []
            typechecked_interface = IsTypeChecking(self._interface)

            for i in reversed(range(0, argument_count)):
                argument = signatures[signature_index][i]
                parameter_name = parameter_names[i]

                test_type = self._NarrowToImplementationType(argument.type.id)

                if test_type in ['dynamic', 'Object']:
                    checks.append('%s != null' % parameter_name)
                elif not can_omit_type_check(test_type, i):
                    typechecked = typechecked_interface or IsTypeChecking(
                        argument)
                    converts_null = \
                        ('TreatNullAs' in argument.ext_attrs) or \
                        (argument.default_value is not None) or \
                        (argument.default_value_is_null)
                    if argument.type.nullable or converts_null or not typechecked:
                        checks.append(
                            '(%s is %s || %s == null)' %
                            (parameter_name, test_type, parameter_name))
                    else:
                        checks.append(
                            '(%s is %s)' % (parameter_name, test_type))
                elif i >= number_of_required_in_dart and not argument.type.nullable:
                    checks.append('%s != null' % parameter_name)

            # There can be multiple presence checks.  We need them all since a later
            # optional argument could have been passed by name, leaving 'holes'.
            checks.extend([
                '%s == null' % name for name in parameter_names[argument_count:]
            ])

            GenerateCall(signature_index, argument_count, checks)

        # TODO: Optimize the dispatch to avoid repeated checks.
        if len(signatures) > 1:
            index_swaps = {}
            for signature_index, signature in enumerate(signatures):
                for argument_position, argument in enumerate(signature):
                    if argument.type.id != 'ArrayBuffer':
                        continue
                    candidates = enumerate(signatures[signature_index + 1:],
                                           signature_index + 1)
                    for candidate_index, candidate in candidates:
                        if len(candidate) <= argument_position:
                            continue
                        if candidate[
                                argument_position].type.id != 'ArrayBufferView':
                            continue
                        if len(index_swaps):
                            raise Exception(
                                'Cannot deal with more than a single swap')
                        index_swaps[candidate_index] = signature_index
                        index_swaps[signature_index] = candidate_index

            for signature_index in range(len(signatures)):
                signature_index = index_swaps.get(signature_index,
                                                  signature_index)
                signature = signatures[signature_index]
                for argument_position, argument in enumerate(signature):
                    if is_optional(signature_index, argument):
                        GenerateChecksAndCall(signature_index,
                                              argument_position)
                GenerateChecksAndCall(signature_index, len(signature))
            body_emitter.Emit(
                '    throw new ArgumentError("Incorrect number or type of arguments");'
                '\n')
        else:
            signature = signatures[0]
            argument_count = len(signature)
            for argument_position, argument in list(enumerate(signature))[::-1]:
                if is_optional(0, argument):
                    check = '%s != null' % parameter_names[argument_position]
                    # argument_count instead of argument_position + 1 is used here to cover one
                    # complicated case with the effectively optional argument in the middle.
                    # Consider foo(x, optional y, [Default=NullString] optional z)
                    # (as of now it's modelled after HTMLMediaElement.webkitAddKey).
                    # y is optional in WebCore, while z is not.
                    # In this case, if y was actually passed, we'd like to emit foo(x, y, z) invocation,
                    # not foo(x, y).
                    GenerateCall(0, argument_count, [check])
                    argument_count = argument_position
            GenerateCall(0, argument_count, [])

    def _GenerateDispatcherBody(self,
                                info,
                                operations,
                                declaration,
                                generate_call,
                                is_optional,
                                can_omit_type_check=lambda type, pos: False):

        def GenerateCall(stmts_emitter, call_emitter, version, signature_index,
                         argument_count):
            generate_call(stmts_emitter, call_emitter, version,
                          operations[signature_index], argument_count)

        def IsOptional(signature_index, argument):
            return is_optional(argument)

        emitter = self._members_emitter

        self._GenerateOverloadDispatcher(
            info, [operation.arguments for operation in operations],
            operations[0].type.id == 'void', declaration, GenerateCall,
            IsOptional, emitter, can_omit_type_check)

    def AdditionalImplementedInterfaces(self):
        # TODO: Include all implemented interfaces, including other Lists.
        implements = []
        if self._interface_type_info.list_item_type():
            item_type = self._type_registry.TypeInfo(
                self._interface_type_info.list_item_type()).dart_type()
            if self._nnbd and \
                    self._interface_type_info.list_item_type_nullable():
                item_type += '?'
            implements.append('List<%s>' % item_type)
        return implements

    def Mixins(self):
        mixins = []
        if self._interface_type_info.list_item_type():
            item_type = self._type_registry.TypeInfo(
                self._interface_type_info.list_item_type()).dart_type()
            if self._nnbd and \
                    self._interface_type_info.list_item_type_nullable():
                item_type += '?'
            mixins.append('ListMixin<%s>' % item_type)
            mixins.append('ImmutableListMixin<%s>' % item_type)

        return mixins

    def AddConstructors(self, constructors, factory_name,
                        factory_constructor_name):
        """ Adds all of the constructors.
    Arguments:
      constructors - List of the constructors to be added.
      factory_name - Name of the factory for this class.
      factory_constructor_name - The name of the constructor on the
          factory_name to call (calls an autogenerated FactoryProvider
          if unspecified)
    """
        for constructor_info in constructors:
            self._AddConstructor(constructor_info, factory_name,
                                 factory_constructor_name)

    def _AddConstructor(self, constructor_info, factory_name,
                        factory_constructor_name):
        # Hack to ignore the constructor used by JavaScript.
        if ((self._interface.id == 'HTMLImageElement' or
             self._interface.id == 'Blob' or
             self._interface.id == 'DOMException') and
                not constructor_info.pure_dart_constructor):
            return

        if self.GenerateCustomFactory(constructor_info):
            return

        metadata = self._metadata.GetFormattedMetadata(
            self._library_name, self._interface, self._interface.id, '  ')

        if not factory_constructor_name:
            factory_constructor_name = '_create'
            factory_parameters = constructor_info.ParametersAsArgumentList()
        else:
            factory_parameters = ', '.join(constructor_info.factory_parameters)

        def InputType(type_name):
            conversion = self._InputConversion(type_name,
                                               constructor_info.declared_name)
            if conversion:
                return conversion.input_type
            else:
                return self._NarrowInputType(
                    type_name) if type_name else 'dynamic'

        if constructor_info.pure_dart_constructor:
            # TODO(antonm): use common dispatcher generation for this case as well.
            has_optional = any(param_info.is_optional
                               for param_info in constructor_info.param_infos)
            factory_call = self.MakeFactoryCall(
                factory_name, factory_constructor_name, factory_parameters,
                constructor_info)
            if not has_optional:
                self._members_emitter.Emit(
                    '\n  $(METADATA)'
                    'factory $CTOR($PARAMS) => '
                    '$FACTORY_CALL;\n',
                    CTOR=constructor_info._ConstructorFullName(self._DartType),
                    PARAMS=constructor_info.ParametersAsDeclaration(InputType),
                    FACTORY_CALL=factory_call,
                    METADATA=metadata)
            else:
                inits = self._members_emitter.Emit(
                    '\n  $(METADATA)'
                    'factory $CONSTRUCTOR($PARAMS) {\n'
                    '    $CONSTRUCTOR e = $FACTORY_CALL;\n'
                    '$!INITS'
                    '    return e;\n'
                    '  }\n',
                    CONSTRUCTOR=constructor_info._ConstructorFullName(
                        self._DartType),
                    METADATA=metadata,
                    FACTORY_CALL=factory_call,
                    PARAMS=constructor_info.ParametersAsDeclaration(InputType))

                for index, param_info in enumerate(
                        constructor_info.param_infos):
                    if param_info.is_optional:
                        inits.Emit(
                            '    if ($E != null) e.$E = $E;\n',
                            E=param_info.name)
        else:
            custom_factory_ctr = self._interface.id in _custom_factories
            if self._interface_type_info.has_generated_interface():
                constructor_full_name = constructor_info._ConstructorFullName(
                    self._DartType)
            else:
                # The interface is suppress_interface so use the implementation_name not
                # the dart_type.
                constructor_full_name = self._interface_type_info.implementation_name(
                )
                factory_name = constructor_full_name

            def GenerateCall(stmts_emitter, call_emitter, version,
                             signature_index, argument_count):
                name = emitter.Format('_create_$VERSION', VERSION=version)
                arguments = constructor_info.idl_args[
                    signature_index][:argument_count]
                args = None
                call_template = ''
                if self._dart_use_blink:
                    type_ids = [p.type.id for p in arguments]
                    base_name, rs = \
                        self.DeriveNativeEntry("constructorCallback", 'Constructor', argument_count)
                    qualified_name = \
                        self.DeriveQualifiedBlinkName(self._interface.id,
                                                      base_name)
                    args = constructor_info.ParametersAsArgumentList(
                        argument_count)

                    # Handle converting Maps to Dictionaries, etc.
                    (factory_params, converted_arguments,
                     calling_params) = self._ConvertArgumentTypes(
                         stmts_emitter, arguments, argument_count,
                         constructor_info)
                    args = ', '.join(converted_arguments)
                    call_template = '$FACTORY_NAME($FACTORY_PARAMS)'
                else:
                    qualified_name = emitter.Format(
                        '$FACTORY.$NAME', FACTORY=factory_name, NAME=name)
                    (factory_params, converted_arguments,
                     calling_params) = self._ConvertArgumentTypes(
                         stmts_emitter, arguments, argument_count,
                         constructor_info)
                    args = ', '.join(converted_arguments)
                    call_template = '$FACTORY_NAME($FACTORY_PARAMS)'
                call_emitter.Emit(
                    call_template,
                    FACTORY_NAME=qualified_name,
                    FACTORY_PARAMS=args)
                self.EmitStaticFactoryOverload(constructor_info, name,
                                               arguments)

            def IsOptional(signature_index, argument):
                return self.IsConstructorArgumentOptional(argument)

            entry_declaration = emitter.Format(
                '$(METADATA)$FACTORY_KEYWORD $CTOR($PARAMS)',
                FACTORY_KEYWORD=('factory' if not custom_factory_ctr else
                                 'static %s' % constructor_full_name),
                CTOR=(('' if not custom_factory_ctr else '_factory') +
                      constructor_full_name),
                METADATA=metadata,
                PARAMS=constructor_info.ParametersAsDeclaration(InputType))

            overload_emitter = self._members_emitter
            overload_declaration = entry_declaration

            self._GenerateOverloadDispatcher(constructor_info,
                                             constructor_info.idl_args, False,
                                             overload_declaration, GenerateCall,
                                             IsOptional, overload_emitter)

    def _AddFutureifiedOperation(self, info, html_name):
        """Given a API function that uses callbacks, convert it to using Futures.

    This conversion assumes the success callback is always provided before the
    error callback (and so far in the DOM API, this is the case)."""
        callback_info = GetCallbackInfo(
            self._database.GetInterface(info.callback_args[0].type_id))

        # Generated private members never have named arguments.
        ignore_named_parameters = True if html_name.startswith('_') else False

        # If more than one callback then the second argument is the error callback.
        # Some error callbacks have 2 args (e.g., executeSql) where the second arg
        # is the error - this is the argument we want.
        error_callback = ""
        if len(info.callback_args) > 1:
            error_callback_info = GetCallbackInfo(
                self._database.GetInterface(info.callback_args[1].type_id))
            error_callbackNames = []
            for paramInfo in error_callback_info.param_infos:
                error_callbackNames.append(paramInfo.name)
            errorCallbackVariables = ", ".join(error_callbackNames)
            errorName = error_callback_info.param_infos[-1].name
            error_callback = (
                ',\n        %s(%s) { completer.completeError(%s); }' % (
                    ('%s : ' % info.callback_args[1].name
                     if info.requires_named_arguments and
                     info.callback_args[1].is_optional and
                     not (ignore_named_parameters) else ''),
                    errorCallbackVariables, errorName))

        extensions = GetDDC_Extension(self._interface, info.declared_name)
        if extensions:
            ddc_extensions = "\n".join(extensions)
        else:
            ddc_extensions = ''

        # Some callbacks have more than one parameters.  If so use all of
        # those parameters.  However, if more than one argument use the
        # type of the last argument to be returned e.g., executeSql the callback
        # is (transaction, resultSet) and only the resultSet is returned SqlResultSet.
        callbackArgsLen = len(callback_info.param_infos)
        future_generic = ''
        callbackVariables = ''
        completerVariable = ''
        if callbackArgsLen == 1:
            callbackVariables = 'value'
            completerVariable = callbackVariables
            if callback_info.param_infos[0].type_id:
                future_generic = '<%s>' % self._DartType(
                    callback_info.param_infos[0].type_id)
        elif callbackArgsLen > 1:
            callbackNames = []
            for paramInfo in callback_info.param_infos:
                callbackNames.append(paramInfo.name)
            callbackVariables = ",".join(callbackNames)
            completerVariable = callbackNames[-1]
            future_generic = '<%s>' % self._DartType(
                callback_info.param_infos[-1].type_id)

        param_list = info.ParametersAsArgumentList(None,
                                                   ignore_named_parameters)
        dictionary_argument = info.dictionaryArgumentName()

        convert_map = ''
        if dictionary_argument is not None:
            mapArg = dictionary_argument[0]
            tempVariable = '%s_dict' % mapArg
            mapArgOptional = dictionary_argument[1]

            if not (extensions):
                if not (param_list.endswith(', mapArg') or
                        param_list.endswith(', options') or
                        param_list == mapArg):
                    print "ERROR: %s.%s - Last parameter or only parameter %s is not of type Map" % (
                        self._interface.id, html_name, mapArg)
                param_list = '%s_dict' % param_list

                if mapArgOptional:
                    convert_map = '    var %s = null;\n'\
                                  '    if (%s != null) {\n'\
                                  '      %s = convertDartToNative_Dictionary(%s);\n'\
                                  '    }\n' % (tempVariable, mapArg, tempVariable, mapArg)
                else:
                    convert_map = '    var %s = convertDartToNative_Dictionary(%s);\n' % (
                        tempVariable, mapArg)

        metadata = ''
        if '_RenamingAnnotation' in dir(self):
            metadata = (
                self._RenamingAnnotation(info.declared_name, html_name) +
                self._Metadata(info.type_name, info.declared_name, None,
                    info.type_nullable))
        self._members_emitter.Emit(
            '\n'
            '  $METADATA$MODIFIERS$TYPE$FUTURE_GENERIC $NAME($PARAMS) {\n'
            '    $CONVERT_DICTIONARY'
            '    var completer = new Completer$(FUTURE_GENERIC)();\n'
            '    $ORIGINAL_FUNCTION($PARAMS_LIST\n'
            '        $NAMED_PARAM($VARIABLE_NAME) { '
            '$DDC_EXTENSION\n'
            'completer.complete($COMPLETER_NAME); }'
            '$ERROR_CALLBACK);\n'
            '    return completer.future;\n'
            '  }\n',
            METADATA=metadata,
            MODIFIERS='static ' if info.IsStatic() else '',
            TYPE=self.SecureOutputType(info.type_name,
                nullable=info.type_nullable),
            NAME=html_name[1:],
            PARAMS=info.
            ParametersAsDeclaration(self._NarrowInputType if '_NarrowInputType'
                                    in dir(self) else self._DartType),
            CONVERT_DICTIONARY=convert_map,
            PARAMS_LIST='' if param_list == '' else param_list + ',',
            NAMED_PARAM=('%s : ' % info.callback_args[0].name
                         if info.requires_named_arguments and
                         info.callback_args[0].is_optional and
                         not (ignore_named_parameters) else ''),
            VARIABLE_NAME=callbackVariables,
            COMPLETER_NAME=completerVariable,
            DDC_EXTENSION=ddc_extensions,
            ERROR_CALLBACK=error_callback,
            FUTURE_GENERIC=future_generic,
            ORIGINAL_FUNCTION=html_name)

    def EmitHelpers(self, base_class):
        if not self._members_emitter:
            return

        if self._interface.id not in custom_html_constructors:
            self._members_emitter.Emit(
                '  // To suppress missing implicit constructor warnings.\n'
                '  factory $CLASSNAME._() { '
                'throw new UnsupportedError("Not supported"); }\n',
                CLASSNAME=self._interface_type_info.implementation_name())

    def DeclareAttribute(self, attribute, type_name, attr_name, read_only):
        """ Declares an attribute but does not include the code to invoke it.
    """
        if read_only:
            # HACK(terry): Element is not abstract for Dartium so isContentEditable
            # must have a body see impl_Element.darttemplate
            if (self._interface.id == 'Element' and
                    attr_name == 'isContentEditable' and self._dart_js_interop):
                return
            else:
                template = '\n  $TYPE get $NAME;\n'
        else:
            template = '\n  $TYPE get $NAME native;\n' \
                       '\n  void set $NAME native;\n'

        self._members_emitter.Emit(template, NAME=attr_name, TYPE=type_name)

    def DeclareOperation(self, operation, return_type_name, method_name):
        """ Declares an operation but does not include the code to invoke it.
    Arguments:
      operation - The operation to be declared.
      return_type_name - The name of the return type.
      method_name - The name of the method.
    """
        # HACK(terry): Element is not abstract for Dartium so click
        # must have a body see impl_Element.darttemplate
        if (self._interface.id == 'Element' and method_name == 'click' and
                self._dart_js_interop):
            return
        else:
            template = '\n  $TYPE $NAME($PARAMS);\n'

        self._members_emitter.Emit(
            template,
            TYPE=return_type_name,
            NAME=method_name,
            PARAMS=operation.ParametersAsDeclaration(self._DartType))

    def EmitListMixin(self, element_name, nullable):
        # TODO(sra): Use separate mixins for mutable implementations of List<T>.
        # TODO(sra): Use separate mixins for typed array implementations of List<T>.
        template_file = 'immutable_list_mixin.darttemplate'
        has_length = False
        has_length_setter = False

        def _HasExplicitIndexedGetter(self):
            return any(op.id == 'getItem' for op in self._interface.operations)

        def _HasCustomIndexedGetter(self):
            return 'CustomIndexedGetter' in self._interface.ext_attrs

        def _HasNativeIndexedGetter(self):
            return not (_HasCustomIndexedGetter(self) or
                        _HasExplicitIndexedGetter(self))

        if _HasExplicitIndexedGetter(self):
            getter_name = 'getItem'
        else:
            getter_name = '_nativeIndexedGetter'

        for attr in self._interface.attributes:
            if attr.id == 'length':
                has_length = True
                has_length_setter = not attr.is_read_only

        has_num_items = any(
            attr.id == 'numberOfItems' for attr in self._interface.attributes)

        template = self._template_loader.Load(
            template_file, {
                'DEFINE_LENGTH_AS_NUM_ITEMS':
                not has_length and has_num_items,
                'DEFINE_LENGTH_SETTER':
                not has_length_setter,
                'USE_NATIVE_INDEXED_GETTER':
                _HasNativeIndexedGetter(self) or
                _HasExplicitIndexedGetter(self),
            })
        if nullable:
            element_js = element_name + "|Null"
            if self._nnbd:
                element_name += '?'
        else:
            element_js = element_name
        self._members_emitter.Emit(
            template, E=element_name, EJS=element_js, GETTER=getter_name)

    def SecureOutputType(self,
                         type_name,
                         is_dart_type=False,
                         can_narrow_type=False,
                         nullable=False):
        """ Converts the type name to the secure type name for return types.
    Arguments:
      can_narrow_type - True if the output type can be narrowed further than
        what would be accepted for input, used to narrow num APIs down to double
        or int.
    """
        if is_dart_type:
            dart_name = type_name
        else:
            type_info = self._TypeInfo(type_name)
            dart_name = type_info.dart_type()
            if can_narrow_type and dart_name == 'num':
                dart_name = type_info.native_type()

        # We only need to secure Window.  Only local History and Location are
        # returned in generated code.
        assert (dart_name != 'HistoryBase' and dart_name != 'LocationBase')
        if dart_name == 'Window':
            dart_name = _secure_base_types[dart_name]
        if self._nnbd:
            if type_name == 'any':
                dart_name = 'Object'
            if nullable and dart_name != 'dynamic':
                dart_name = dart_name + '?'
        return dart_name

    def SecureBaseName(self, type_name):
        if type_name in _secure_base_types:
            return _secure_base_types[type_name]

    def is_DOM_type(self, type_name):
        try:
            self._type_registry.TypeInfo(type_name)
            return True
        except RuntimeError:
            return False

    def _NarrowToImplementationType(self, type_name):
        return self._type_registry.TypeInfo(type_name).narrow_dart_type()

    def _NarrowInputType(self, type_name):
        return self._NarrowToImplementationType(type_name)

    def _DartType(self, type_name):
        return self._type_registry.DartType(type_name)

    def _TypeInfo(self, type_name):
        return self._type_registry.TypeInfo(type_name)

    def _CallbackConvert(self, argType, info):
        if self._database.HasInterface(argType):
            interface = self._database.GetInterface(argType)
            if "Callback" in interface.ext_attrs:
                return interface.ext_attrs['Callback']
        return None

    def _ConvertArgumentTypes(self, stmts_emitter, arguments, argument_count,
                              info):
        temp_version = [0]
        converted_arguments = []
        target_parameters = []
        calling_parameters = []
        for position, arg in enumerate(arguments[:argument_count]):
            callBackInfo = self._CallbackConvert(
                arg.type.id, info)  # Returns callback arity (# of parameters)
            if callBackInfo is None:
                conversion = self._InputConversion(arg.type.id,
                                                   info.declared_name)
            else:
                conversion = self._InputConversion('Callback',
                                                   info.declared_name)

            param_name = arguments[position].id
            if conversion:
                temp_version[0] += 1
                temp_name = '%s_%s' % (param_name, temp_version[0])
                temp_type = conversion.output_type
                null_assert_needed = info.param_infos[position].is_nullable \
                    and not conversion.nullable_input
                stmts_emitter.Emit(
                    '$(INDENT)$TYPE $NAME = $CONVERT($ARG$NULLASSERT);\n'
                    if callBackInfo is None else
                    '$(INDENT)$TYPE $NAME = $CONVERT($ARG$NULLASSERT, $ARITY);\n',
                    TYPE=TypeOrVar(temp_type),
                    NAME=temp_name,
                    CONVERT=conversion.function_name,
                    ARG=info.param_infos[position].name,
                    NULLASSERT='!' if null_assert_needed and self._nnbd else '',
                    ARITY=callBackInfo)
                converted_arguments.append(temp_name)
                param_type = temp_type
                verified_type = temp_type  # verified by assignment in checked mode.
            else:
                converted_arguments.append(info.param_infos[position].name)
                if self._database.HasTypeDef(arg.type.id):
                    param_type = 'dynamic'
                else:
                    param_type = self._NarrowInputType(arg.type.id)
                    # Verified by argument checking on entry to the dispatcher.

                    verified_type = self._InputType(
                        info.param_infos[position].type_id, info)
                    # The native method does not need an argument type if we know the type.
                    # But we do need the native methods to have correct function types, so
                    # be conservative.
                    if param_type == verified_type:
                        if param_type in [
                                'String', 'num', 'int', 'double', 'bool',
                                'Object'
                        ]:
                            param_type = 'dynamic'
            arg_is_nullable = arg.type.nullable
            # If the parameter is either nullable or optional with no non-null
            # default value, it is nullable.
            if (info.param_infos[position].is_optional and
                (info.param_infos[position].default_value_is_null == True or
                 info.param_infos[position].default_value == None)
               ) or info.param_infos[position].is_nullable:
                arg_is_nullable = True
            target_parameters.append(
                '%s%s' % (TypeOrNothing(param_type, nullable=arg_is_nullable),
                          param_name))
            calling_parameters.append(',%s ' % param_name)

        return target_parameters, converted_arguments, calling_parameters

    def _InputType(self, type_name, info):
        conversion = self._InputConversion(type_name, info.declared_name)
        if conversion:
            return conversion.input_type
        else:
            # If typedef it's a union return dynamic.
            if self._database.HasTypeDef(type_name):
                return 'dynamic'
            else:
                return self._NarrowInputType(
                    type_name) if type_name else 'dynamic'
