# Copyright (C) 2013 Google Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
#     * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
#     * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

"""Resolve interface dependencies, producing a merged IdlDefinitions object.

This library computes interface dependencies (partial interfaces and
implements), reads the dependency files, and merges them to the IdlDefinitions
for the main IDL file, producing an IdlDefinitions object representing the
entire interface.

Design doc: http://www.chromium.org/developers/design-documents/idl-compiler#TOC-Dependency-resolution
"""

import os.path
from utilities import idl_filename_to_component, is_valid_component_dependency, merge_dict_recursively

# The following extended attributes can be applied to a dependency interface,
# and are then applied to the individual members when merging.
# Note that this moves the extended attribute from the interface to the member,
# which changes the semantics and yields different code than the same extended
# attribute on the main interface.
DEPENDENCY_EXTENDED_ATTRIBUTES = frozenset([
    'OriginTrialEnabled',
    'RuntimeEnabled',
    'SecureContext',
])


class InterfaceDependencyResolver(object):
    def __init__(self, interfaces_info, reader):
        """Initialize dependency resolver.

        Args:
            interfaces_info:
                dict of interfaces information, from compute_dependencies.py
            reader:
                IdlReader, used for reading dependency files
        """
        self.interfaces_info = interfaces_info
        self.reader = reader

    def resolve_dependencies(self, definitions, component):
        """Resolve dependencies, merging them into IDL definitions of main file.

        Dependencies consist of 'partial interface' for the same interface as
        in the main file, and other interfaces that this interface 'implements'.
        These are merged into the main IdlInterface, as the main IdlInterface
        implements all these members.

        Referenced interfaces are added to IdlDefinitions, but not merged into
        the main IdlInterface, as these are only referenced (their members are
        introspected, but not implemented in this interface).

        Inherited extended attributes are also added to the main IdlInterface.

        Modifies definitions in place by adding parsed dependencies.

        Args:
            definitions: IdlDefinitions object, modified in place
            component:
                string, describing where the above definitions are defined,
                'core' or 'modules'. See KNOWN_COMPONENTS in utilities.py

        Returns:
            A dictionary whose key is component and value is IdlDefinitions
            object whose dependency is resolved.

        Raises:
            Exception:
                A given IdlDefinitions object doesn't have any interfaces,
                or a given IdlDefinitions object has incorrect referenced
                interfaces.
        """
        # FIXME: we need to resolve dependency when we implement partial
        # dictionary.
        if not definitions.interfaces:
            raise Exception('No need to resolve any dependencies of '
                            'this definition: %s, because this should '
                            'have a dictionary.' % definitions.idl_name)

        target_interface = next(iter(definitions.interfaces.values()))
        interface_name = target_interface.name
        interface_info = self.interfaces_info[interface_name]

        if 'inherited_extended_attributes' in interface_info:
            target_interface.extended_attributes.update(
                interface_info['inherited_extended_attributes'])

        resolved_definitions = merge_interface_dependencies(
            definitions,
            component,
            target_interface,
            interface_info['dependencies_full_paths'] +
            interface_info['dependencies_other_component_full_paths'],
            self.reader)

        inherit_unforgeable_attributes(resolved_definitions, self.interfaces_info)

        for referenced_interface_name in interface_info['referenced_interfaces']:
            referenced_definitions = self.reader.read_idl_definitions(
                self.interfaces_info[referenced_interface_name]['full_path'])

            for referenced_component in referenced_definitions:
                if not is_valid_component_dependency(component, referenced_component):
                    raise Exception('This definitions: %s is defined in %s '
                                    'but reference interface:%s is defined '
                                    'in %s' % (definitions.idl_name,
                                               component,
                                               referenced_interface_name,
                                               referenced_component))

                resolved_definitions[component].update(referenced_definitions[component])

        return resolved_definitions


def merge_interface_dependencies(definitions, component, target_interface, dependency_idl_filenames, reader):
    """Merge dependencies ('partial interface' and 'implements') in dependency_idl_filenames into target_interface.

    Args:
        definitions: IdlDefinitions object, modified in place
        component:
            string, describing where the above definitions are defined,
            'core' or 'modules'. See KNOWN_COMPONENTS in utilities.py
        target_interface: IdlInterface object, modified in place
        dependency_idl_filenames:
            Idl filenames which depend on the above definitions.
        reader: IdlReader object.
    Returns:
        A dictionary whose key is component and value is IdlDefinitions
        object whose dependency is resolved.
    """
    resolved_definitions = {component: definitions}
    # Sort so order consistent, so can compare output from run to run.
    for dependency_idl_filename in sorted(dependency_idl_filenames):
        dependency_definitions = reader.read_idl_file(dependency_idl_filename)
        # For Cobalt, always use the component where |definitions| is located
        # so interfaces will get merged together.
        dependency_component = component

        dependency_interface = next(iter(dependency_definitions.interfaces.values()))
        dependency_interface_basename, _ = os.path.splitext(os.path.basename(dependency_idl_filename))

        transfer_extended_attributes(dependency_interface,
                                     dependency_interface_basename)

        # We need to use different checkdeps here for partial interface and
        # inheritance.
        if dependency_interface.is_partial:
            # Case: dependency_interface is a partial interface of
            # target_interface.
            # So,
            # - A partial interface defined in modules can update
            #   the original interface defined in core.
            # However,
            # - A partial interface defined in core cannot update
            #   the original interface defined in modules.
            if not is_valid_component_dependency(dependency_component, component):
                raise Exception('The partial interface:%s in %s cannot update '
                                'the original interface:%s in %s' % (dependency_interface.name,
                                                                     dependency_component,
                                                                     target_interface.name,
                                                                     component))

            if dependency_component in resolved_definitions:
                # When merging a new partial interfaces, should not overwrite
                # ImpelemntedAs extended attributes in merged partial
                # interface.
                # See also the below "if 'ImplementedAs' not in ... " line's
                # comment.
                dependency_interface.extended_attributes.pop('ImplementedAs', None)
                resolved_definitions[dependency_component].update(dependency_definitions)
                continue

            dependency_interface.extended_attributes.update(target_interface.extended_attributes)
            assert target_interface == definitions.interfaces[dependency_interface.name]
            # A partial interface should use its original interface's
            # ImplementedAs. If the original interface doesn't have,
            # remove ImplementedAs defined in the partial interface.
            # Because partial interface needs the original interface's
            # cpp class to obtain partial interface's cpp class.
            # e.g.. V8WindowPartial.cpp:
            #   DOMWindow* impl = V8Window::toImpl(holder);
            #   DOMWindowQuota* cppValue(DOMWindowQuota::webkitStorageInfo(impl));
            # TODO(tasak): remove ImplementedAs extended attributes
            # from all partial interfaces. Instead, rename all cpp/header
            # files correctly. ImplementedAs should not be allowed in
            # partial interfaces.
            if 'ImplementedAs' not in target_interface.extended_attributes:
                dependency_interface.extended_attributes.pop('ImplementedAs', None)
            dependency_interface.original_interface = target_interface
            target_interface.partial_interfaces.append(dependency_interface)
            resolved_definitions[dependency_component] = dependency_definitions
        else:
            # Case: target_interface implements dependency_interface.
            # So,
            # - An interface defined in modules can implement some interface
            #   defined in core.
            #   In this case, we need "NoInterfaceObject" extended attribute.
            # However,
            # - An interface defined in core cannot implement any interface
            #   defined in modules.
            if not is_valid_component_dependency(component, dependency_component):
                raise Exception('The interface:%s in %s cannot implement '
                                'the interface:%s in %s.' % (dependency_interface.name,
                                                             dependency_component,
                                                             target_interface.name,
                                                             component))

            if component != dependency_component and 'NoInterfaceObject' not in dependency_interface.extended_attributes:
                raise Exception('The interface:%s in %s cannot implement '
                                'the interface:%s in %s because of '
                                'missing NoInterfaceObject.' % (dependency_interface.name,
                                                                dependency_component,
                                                                target_interface.name,
                                                                component))

            resolved_definitions[component].update(dependency_definitions)  # merges partial interfaces
            # Implemented interfaces (non-partial dependencies) are also merged
            # into the target interface, so Code Generator can just iterate
            # over one list (and not need to handle 'implements' itself).
            target_interface.merge(dependency_interface)

    return resolved_definitions


def transfer_extended_attributes(dependency_interface, dependency_interface_basename):
    """Transfer extended attributes from dependency interface onto members.

    Merging consists of storing certain interface-level data in extended
    attributes of the *members* (because there is no separate dependency
    interface post-merging).

    The data storing consists of:
    * moving certain extended attributes from the dependency interface
      to its members (deleting the extended attribute from the interface)
    * storing the C++ class of the implementation in an internal
      extended attribute of each member, [PartialInterfaceImplementedAs]

    No return: modifies dependency_interface in place.
    """
    merged_extended_attributes = {}
    for key in DEPENDENCY_EXTENDED_ATTRIBUTES:
        if key not in dependency_interface.extended_attributes:
            continue

        merged_extended_attributes[key] = dependency_interface.extended_attributes[key]
        # Remove the merged attributes from the original dependency interface.
        # This ensures that if other dependency interfaces are merged onto this
        # one, its extended_attributes do not leak through
        # (https://crbug.com/603782).
        del dependency_interface.extended_attributes[key]

    # A partial interface's members are implemented as static member functions
    # in a separate C++ class. This class name is stored in
    # [PartialInterfaceImplementedAs] which defaults to the basename of
    # dependency IDL file.
    # This class name can be overridden by [ImplementedAs] on the partial
    # interface definition.
    #
    # Note that implemented interfaces do *not* need [ImplementedAs], since
    # they are implemented on the C++ object |impl| itself, just like members of
    # the main interface definition, so the bindings do not need to know in
    # which class implemented interfaces are implemented.
    #
    # Currently [LegacyTreatAsPartialInterface] can be used to have partial
    # interface behavior on implemented interfaces, but this is being removed
    # as legacy cruft:
    # FIXME: Remove [LegacyTreatAsPartialInterface]
    # http://crbug.com/360435
    #
    # Note that [ImplementedAs] is used with different meanings on interfaces
    # and members:
    # for Blink class name and function name (or constant name), respectively.
    # Thus we do not want to copy this from the interface to the member, but
    # instead extract it and handle it separately.
    if (dependency_interface.is_partial or
        'LegacyTreatAsPartialInterface' in dependency_interface.extended_attributes):
        merged_extended_attributes['PartialInterfaceImplementedAs'] = (
            dependency_interface.extended_attributes.pop(
                'ImplementedAs', dependency_interface_basename))

    def update_attributes(attributes, extras):
        for key, value in extras.items():
            if key not in attributes:
                attributes[key] = value

    for attribute in dependency_interface.attributes:
        update_attributes(attribute.extended_attributes, merged_extended_attributes)
    for constant in dependency_interface.constants:
        update_attributes(constant.extended_attributes, merged_extended_attributes)
    for operation in dependency_interface.operations:
        update_attributes(operation.extended_attributes, merged_extended_attributes)


def inherit_unforgeable_attributes(resolved_definitions, interfaces_info):
    """Inherits [Unforgeable] attributes and updates the arguments accordingly.

    For each interface in |resolved_definitions|, collects all [Unforgeable]
    attributes in ancestor interfaces in the same component and adds them to
    the interface.  'referenced_interfaces' and 'cpp_includes' in
    |interfaces_info| are updated accordingly.
    """
    def collect_unforgeable_attributes_in_ancestors(interface_name, component):
        if not interface_name:
            # unforgeable_attributes, referenced_interfaces, cpp_includes
            return [], [], set()
        interface = interfaces_info[interface_name]
        unforgeable_attributes, referenced_interfaces, cpp_includes = collect_unforgeable_attributes_in_ancestors(interface.get('parent'), component)
        this_unforgeable = interface.get('unforgeable_attributes', {}).get(component, [])
        unforgeable_attributes.extend(this_unforgeable)
        this_referenced = [attr.idl_type.base_type for attr in this_unforgeable
                           if attr.idl_type.base_type in
                           interface.get('referenced_interfaces', [])]
        referenced_interfaces.extend(this_referenced)
        cpp_includes.update(interface.get('cpp_includes', {}).get(component, {}))
        return unforgeable_attributes, referenced_interfaces, cpp_includes

    for component, definitions in resolved_definitions.items():
        for interface_name, interface in definitions.interfaces.items():
            interface_info = interfaces_info[interface_name]
            inherited_unforgeable_attributes, referenced_interfaces, cpp_includes = collect_unforgeable_attributes_in_ancestors(interface_info.get('parent'), component)
            # This loop may process the same interface many times, so it's
            # possible that we're adding the same attributes twice or more.
            # So check if there is a duplicate.
            for attr in inherited_unforgeable_attributes:
                if attr not in interface.attributes:
                    interface.attributes.append(attr)
            referenced_interfaces.extend(interface_info.get('referenced_interfaces', []))
            interface_info['referenced_interfaces'] = sorted(set(referenced_interfaces))
            merge_dict_recursively(interface_info,
                                   {'cpp_includes': {component: cpp_includes}})
