#!/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 generates Dart APIs from the IDL database."""

import emitter
import idlnode
import logging
import os
import re
import shutil
from generator import *
from idlnode import IDLType, IDLInterface, resolveTypedef

_logger = logging.getLogger('dartgenerator')


def MergeNodes(node, other):
    node.operations.extend(other.operations)
    for attribute in other.attributes:
        if not node.has_attribute(attribute):
            node.attributes.append(attribute)

    node.constants.extend(other.constants)


class DartGenerator(object):
    """Utilities to generate Dart APIs and corresponding JavaScript."""

    def __init__(self, logging_level=logging.WARNING):
        self._auxiliary_files = {}
        self._dart_templates_re = re.compile(r'[\w.:]+<([\w \.<>:]+)>')
        _logger.setLevel(logging_level)

    def _StripModules(self, type_name):
        return type_name.split('::')[-1]

    def _IsCompoundType(self, database, type_name):
        if IsRegisteredType(type_name):
            return True

        # References a typedef - normally a union type.
        if database.HasTypeDef(type_name):
            return True

        if type_name.endswith('?'):
            return self._IsCompoundType(database, type_name[:-len('?')])

        if type_name.endswith('[]'):
            return self._IsCompoundType(database, type_name[:-len('[]')])

        stripped_type_name = self._StripModules(type_name)
        if (database.HasInterface(stripped_type_name) or
                database.HasDictionary(stripped_type_name)):
            return True

        if database.HasEnum(stripped_type_name):
            return True

        dart_template_match = self._dart_templates_re.match(type_name)
        if dart_template_match:
            # Dart templates
            parent_type_name = type_name[0:dart_template_match.start(1) - 1]
            sub_type_name = dart_template_match.group(1)
            return (self._IsCompoundType(database, parent_type_name) and
                    self._IsCompoundType(database, sub_type_name))
        return False

    def _IsDartType(self, type_name):
        return '.' in type_name

    def LoadAuxiliary(self, auxiliary_dir):

        for (dirname, _, names) in os.walk(auxiliary_dir):
            for name in names:
                if name.endswith('.dart'):
                    name = name[0:-5]  # strip off ".dart"
                self._auxiliary_files[name] = os.path.join(dirname, name)

    def FilterMembersWithUnidentifiedTypes(self, database):
        """Removes unidentified types.

    Removes constants, attributes, operations and parents with unidentified
    types.
    """

        for interface in database.GetInterfaces():

            def IsIdentified(idl_node):
                node_name = idl_node.id if idl_node.id else 'parent'
                for idl_type in idl_node.all(idlnode.IDLType):
                    type_name = idl_type.id
                    if (type_name is not None and
                            self._IsCompoundType(database, type_name)):
                        continue
                    # Ignore constructor warnings.
                    if not (interface.id in [
                            'Window', 'WorkerContext', 'WorkerGlobalScope'
                    ] and type_name.endswith('Constructor')):
                        _logger.warn(
                            'removing %s in %s which has unidentified type %s' %
                            (node_name, interface.id, type_name))
                    return False
                return True

            interface.constants = list(filter(IsIdentified,
                                              interface.constants))
            interface.attributes = list(
                filter(IsIdentified, interface.attributes))
            interface.operations = list(
                filter(IsIdentified, interface.operations))
            interface.parents = list(filter(IsIdentified, interface.parents))

    def FilterInterfaces(self,
                         database,
                         and_annotations=[],
                         or_annotations=[],
                         exclude_displaced=[],
                         exclude_suppressed=[]):
        """Filters a database to remove interfaces and members that are missing
    annotations.

    The FremontCut IDLs use annotations to specify implementation
    status in various platforms. For example, if a member is annotated
    with @WebKit, this means that the member is supported by WebKit.

    Args:
      database -- the database to filter
      all_annotations -- a list of annotation names a member has to
        have or it will be filtered.
      or_annotations -- if a member has one of these annotations, it
        won't be filtered even if it is missing some of the
        all_annotations.
      exclude_displaced -- if a member has this annotation and it
        is marked as displaced it will always be filtered.
      exclude_suppressed -- if a member has this annotation and it
        is marked as suppressed it will always be filtered.
    """

        # Filter interfaces and members whose annotations don't match.
        for interface in database.GetInterfaces():

            def HasAnnotations(idl_node):
                """Utility for determining if an IDLNode has all
        the required annotations"""
                for a in exclude_displaced:
                    if (a in idl_node.annotations and
                            'via' in idl_node.annotations[a]):
                        return False
                for a in exclude_suppressed:
                    if (a in idl_node.annotations and
                            'suppressed' in idl_node.annotations[a]):
                        return False
                for a in or_annotations:
                    if a in idl_node.annotations:
                        return True
                if and_annotations == []:
                    return False
                for a in and_annotations:
                    if a not in idl_node.annotations:
                        return False
                return True

            if HasAnnotations(interface):
                interface.constants = filter(HasAnnotations,
                                             interface.constants)
                interface.attributes = filter(HasAnnotations,
                                              interface.attributes)
                interface.operations = filter(HasAnnotations,
                                              interface.operations)
                interface.parents = filter(HasAnnotations, interface.parents)
            else:
                database.DeleteInterface(interface.id)

        self.FilterMembersWithUnidentifiedTypes(database)

    def Generate(self, database, super_database, generate_interface):
        self._database = database

        # Collect interfaces
        interfaces = []
        for interface in database.GetInterfaces():
            if not MatchSourceFilter(interface):
                # Skip this interface since it's not present in the required source
                _logger.info('Omitting interface - %s' % interface.id)
                continue
            interfaces.append(interface)

        # All web_gl constants from WebGLRenderingContextBase, WebGL2RenderingContextBase, WebGLDrawBuffers are generated
        # in a synthesized class WebGL.  Those IDLConstants are in web_gl_constants.
        web_gl_constants = []

        # Render all interfaces into Dart and save them in files.
        for interface in self._PreOrderInterfaces(interfaces):
            interface_name = interface.id
            auxiliary_file = self._auxiliary_files.get(interface_name)
            if auxiliary_file is not None:
                _logger.info('Skipping %s because %s exists' % (interface_name,
                                                                auxiliary_file))
                continue

            _logger.info('Generating %s' % interface.id)
            generate_interface(interface, gl_constants=web_gl_constants)

        # Generate the WEB_GL constants
        web_gl_constants_interface = IDLInterface(None, "WebGL")
        web_gl_constants_interface.constants = web_gl_constants
        self._database._all_interfaces['WebGL'] = web_gl_constants_interface
        generate_interface(web_gl_constants_interface)

    def _PreOrderInterfaces(self, interfaces):
        """Returns the interfaces in pre-order, i.e. parents first."""
        seen = set()
        ordered = []

        def visit(interface):
            if interface.id in seen:
                return
            seen.add(interface.id)
            for parent in interface.parents:
                if IsDartCollectionType(parent.type.id):
                    continue
                if self._database.HasInterface(parent.type.id):
                    parent_interface = self._database.GetInterface(
                        parent.type.id)
                    visit(parent_interface)
            ordered.append(interface)

        for interface in interfaces:
            visit(interface)
        return ordered

    def IsEventTarget(self, database, interface):
        if interface.id == 'EventTarget':
            return True
        for parent in interface.parents:
            parent_name = parent.type.id
            if database.HasInterface(parent_name):
                parent_interface = database.GetInterface(parent.type.id)
                if self.IsEventTarget(database, parent_interface):
                    return True
        return False

    def FixEventTargets(self, database):
        for interface in database.GetInterfaces():
            if self.IsEventTarget(database, interface):
                # Add as an attribute for easy querying in generation code.
                interface.ext_attrs['EventTarget'] = None
            elif 'EventTarget' in interface.ext_attrs:
                # Create fake EventTarget parent interface for interfaces that have
                # 'EventTarget' extended attribute.
                ast = [('Annotation', [('Id', 'WebKit')]),
                       ('InterfaceType', ('ScopedName', 'EventTarget'))]
                interface.parents.append(idlnode.IDLParentInterface(ast))

    def AddMissingArguments(self, database):
        ARG = idlnode.IDLArgument([('Type', ('ScopedName', 'object')),
                                   ('Id', 'arg')])
        for interface in database.GetInterfaces():
            for operation in interface.operations:
                call_with = operation.ext_attrs.get('CallWith', [])
                if not (isinstance(call_with, list)):
                    call_with = [call_with]
                constructor_with = operation.ext_attrs.get(
                    'ConstructorCallWith', [])
                if not (isinstance(constructor_with, list)):
                    constructor_with = [constructor_with]
                call_with = call_with + constructor_with

                if 'ScriptArguments' in call_with:
                    operation.arguments.append(ARG)

    def CleanupOperationArguments(self, database):
        for interface in database.GetInterfaces():
            for operation in interface.operations:
                # TODO(terry): Hack to remove 3rd arguments in setInterval/setTimeout.
                if ((operation.id == 'setInterval' or operation.id == 'setTimeout') and \
                    operation.arguments[0].type.id == 'any'):
                    operation.arguments.pop(2)

                # Massage any operation argument type that is IDLEnum to String.
                for index, argument in enumerate(operation.arguments):
                    type_name = argument.type.id
                    if database.HasEnum(type_name):
                        operation.arguments[index].type = IDLType('DOMString')
