#!/usr/bin/env python3
# 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
from mdnreader import MDNReader
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)
        self._mdn_reader = MDNReader()
        _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, key=ConstantOutputOrder):
                self.AddConstant(const)

        for attr in sorted(interface.attributes, key=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)
            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,
                                       key=ConstantOutputOrder):
            if isinstance(parent_interface, str):
                continue

            for attr in sorted(parent_interface.attributes,
                               key=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(
                    list(
                        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, 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._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._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, constructor_emitter):
        """ 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)
      constructor_emitter - Emitter used to emit constructors when generating
          classes using the static extension pattern.
    """
        for constructor_info in constructors:
            self._AddConstructor(constructor_info, factory_name,
                                 factory_constructor_name, constructor_emitter)

    def _AddConstructor(self, constructor_info, factory_name,
                        factory_constructor_name, constructor_emitter):
        # 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, '  ')

        target_emitter = constructor_emitter if constructor_emitter else \
            self._members_emitter

        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:
                target_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 = target_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, constructor_emitter)

            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_declaration = entry_declaration

            self._GenerateOverloadDispatcher(constructor_info,
                                             constructor_info.idl_args, False,
                                             overload_declaration, GenerateCall,
                                             IsOptional, target_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, members_emitter):
        if (not self._members_emitter) and (not members_emitter):
            return

        if self._interface.id not in custom_html_constructors:
            target_emitter = members_emitter if members_emitter else \
                self._members_emitter
            target_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, 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  set $NAME($TYPE value) native;\n'

        # Nullability is determined by attribute compatibility.
        is_compat = self._mdn_reader.is_compatible(attribute)
        nullable = attribute.type.nullable or not is_compat

        self._members_emitter.Emit(template,
                                   NAME=attr_name,
                                   TYPE=self.SecureOutputType(
                                       attribute.type.id, nullable=nullable))

    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"
            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 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 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'
