# Copyright 2016 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

# pylint: disable=import-error,print-statement,relative-import

"""Generates Web Agent API bindings.

The Web Agent API bindings provide a stable, IDL-generated interface for the
Web Agents.

The Web Agents are the high-level services like Autofill,
Autocomplete, Translate, Distiller, Phishing Detector, and others. Web Agents
typically want to introspec the document and rendering infromation to implement
browser features.

The bindings are meant to be as simple and as ephemeral as possible, mostly just
wrapping existing DOM classes. Their primary goal is to avoid leaking the actual
DOM classes to the Web Agents layer.
"""

import os
import posixpath
import sys

from code_generator import CodeGeneratorBase, render_template
# TODO(dglazkov): Move TypedefResolver to code_generator.py
from code_generator_v8 import TypedefResolver

sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', '..', '..', '..',
                             'third_party', 'blink', 'tools'))
from blinkpy.common.name_style_converter import NameStyleConverter

MODULE_PYNAME = os.path.splitext(os.path.basename(__file__))[0] + '.py'

STRING_INCLUDE_PATH = 'platform/wtf/text/WTFString.h'
WEB_AGENT_API_IDL_ATTRIBUTE = 'WebAgentAPI'


def interface_context(idl_interface, type_resolver):
    builder = InterfaceContextBuilder(MODULE_PYNAME, type_resolver)
    builder.set_class_name(idl_interface.name)
    builder.set_inheritance(idl_interface.parent)

    for idl_attribute in idl_interface.attributes:
        builder.add_attribute(idl_attribute)

    for idl_operation in idl_interface.operations:
        builder.add_operation(idl_operation)

    return builder.build()


class TypeResolver(object):
    """Resolves Web IDL types into corresponding C++ types and include paths
       to the generated and existing files."""

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

    def includes_from_interface(self, interface_name):
        interface_info = self.interfaces_info.get(interface_name)
        if interface_info is None:
            raise KeyError('Unknown interface "%s".' % interface_name)
        return set([interface_info['include_path']])

    def _includes_from_type(self, idl_type):
        if idl_type.is_void:
            return set()
        if idl_type.is_primitive_type:
            return set()
        if idl_type.is_string_type:
            return set([STRING_INCLUDE_PATH])

        # TODO(dglazkov): Handle complex/weird types.
        return self.includes_from_interface(idl_type.base_type)

    def includes_from_definition(self, idl_definition):
        return self._includes_from_type(idl_definition.idl_type)

    def type_from_definition(self, idl_definition):
        # TODO(dglazkov): The output of this method must be a reasonable C++
        # type that can be used directly in the jinja2 template.
        return idl_definition.idl_type.base_type

    def base_class_includes(self):
        return set(['platform/heap/Handle.h'])


class MethodOverloadSplitter(object):
    """Because of union and optional types being used as arguments, some
       operations may result in more than one generated method. This class
       contains the logic for spliting an operation into multiple C++ overloads.
    """

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

    def _update_argument_lists(self, argument_lists, idl_types):
        """Given a list of IdlTypes and an existing list of argument lists (yes,
           this is a list of lists), produces a next generation of the list of
           lists. This is where the actual splitting into overloads happens.
        """
        result = []
        for argument_list in argument_lists:
            for idl_type in idl_types:
                new_argument_list = list(argument_list)
                if idl_type is not None:
                    new_argument_list.append(idl_type)
                result.append(new_argument_list)
        return result

    def _enumerate_argument_types(self, idl_argument):
        """Given an IdlArgument, returns a list of types that are included
           in this argument. If optional, the list will include a 'None'."""
        argument_type = idl_argument.idl_type
        # TODO(dglazkov): What should we do with primitive nullable args?
        if (argument_type.is_nullable and
                argument_type.inner_type.is_primitive_type):
            raise ValueError('Primitive nullable types are not supported.')

        idl_types = []
        if idl_argument.is_optional:
            idl_types.append(None)  # None is used to convey optionality.
        if argument_type.is_union_type:
            idl_types = idl_types + argument_type.member_types
        else:
            idl_types.append(argument_type)
        return idl_types

    def split_into_overloads(self):
        """Splits an operation into one or more overloads that correctly reflect
           the WebIDL semantics of the operation arguments. For example,
           running this method on an IdlOperation that represents this WebIDL
           definition:

           void addEventListener(
                DOMString type,
                EventListener? listener,
                optional (AddEventListenerOptions or boolean) options)

            will produce a list of 3 argument lists:

            1) [DOMString, EventListener], since the third argument is optional,
            2) [DOMString, EventListener, AddEventListenerOptions], since the
               third argument is a union type with AddEventListenerOptions as
               one of its member types, and
            3) [DOMString, EventListener, boolean], since the other union member
               type of the third argument is boolean.

            This example is also captured as test in
            MethodOverloadSplitterTest.test_split_add_event_listener.
        """

        argument_lists = [[]]
        for idl_argument in self.idl_operation.arguments:
            idl_types = self._enumerate_argument_types(idl_argument)
            argument_lists = self._update_argument_lists(argument_lists,
                                                         idl_types)
        return argument_lists


class InterfaceContextBuilder(object):
    def __init__(self, code_generator, type_resolver):
        self.result = {'code_generator': code_generator}
        self.type_resolver = type_resolver

    def set_class_name(self, class_name):
        converter = NameStyleConverter(class_name)
        self.result['class_name'] = converter.to_all_cases()
        self._ensure_set('cpp_includes').update(
            self.type_resolver.includes_from_interface(class_name))

    def set_inheritance(self, base_interface):
        if base_interface is None:
            self._ensure_set('header_includes').update(
                self.type_resolver.base_class_includes())
            return
        self.result['base_class'] = base_interface
        self._ensure_set('header_includes').update(
            self.type_resolver.includes_from_interface(base_interface))

    def _ensure_set(self, name):
        return self.result.setdefault(name, set())

    def _ensure_list(self, name):
        return self.result.setdefault(name, [])

    def add_attribute(self, idl_attribute):
        self._ensure_list('attributes').append(
            self.create_attribute(idl_attribute))
        self._ensure_set('cpp_includes').update(
            self.type_resolver.includes_from_definition(idl_attribute))

    def add_operation(self, idl_operation):
        if not idl_operation.name:
            return
        overload_splitter = MethodOverloadSplitter(idl_operation)
        overloads = overload_splitter.split_into_overloads()
        argument_names = [argument.name for argument
                          in idl_operation.arguments]
        for argument_types in overloads:
            arguments = []
            for position, argument_type in enumerate(argument_types):
                arguments.append(
                    self.create_argument(argument_names[position],
                                         argument_type))
            self._ensure_list('methods').append(
                self.create_method(idl_operation, arguments))
            self._ensure_set('cpp_includes').update(
                self.type_resolver.includes_from_definition(idl_operation))

    def create_argument(self, argument_name, argument_type):
        name_converter = NameStyleConverter(argument_name)
        return {
            'name': name_converter.to_snake_case(),
            'type': argument_type.base_type,
        }

    def create_method(self, idl_operation, arguments):
        name_converter = NameStyleConverter(idl_operation.name)
        return_type = self.type_resolver.type_from_definition(idl_operation)
        return {
            'name': name_converter.to_upper_camel_case(),
            'type': return_type,
            'arguments': arguments
        }

    def create_attribute(self, idl_attribute):
        name = idl_attribute.name
        return_type = self.type_resolver.type_from_definition(idl_attribute)
        return {
            'name': name,
            'type': return_type
        }

    def build(self):
        return self.result


class CodeGeneratorWebAgentAPI(CodeGeneratorBase):
    def __init__(self, info_provider, cache_dir, output_dir, snake_case):
        CodeGeneratorBase.__init__(self, MODULE_PYNAME, info_provider,
                                   cache_dir, output_dir, snake_case)
        self.type_resolver = TypeResolver(info_provider.interfaces_info)
        self.typedef_resolver = TypedefResolver(info_provider)

    def get_template(self, file_extension):
        template_filename = 'web_agent_api_interface.%s.tmpl' % file_extension
        return self.jinja_env.get_template(template_filename)

    def generate_file(self, template_context, file_extension):
        template = self.get_template(file_extension)
        path = posixpath.join(
            self.output_dir,
            '%s.%s' % (template_context['class_name']['snake_case'],
                       file_extension))
        text = render_template(template, template_context)
        return (path, text)

    def generate_interface_code(self, interface):
        # TODO(dglazkov): Implement callback interfaces.
        # TODO(dglazkov): Make sure partial interfaces are handled.
        if interface.is_callback or interface.is_partial:
            raise ValueError('Partial or callback interfaces are not supported')

        template_context = interface_context(interface, self.type_resolver)

        return (
            self.generate_file(template_context, 'h'),
            self.generate_file(template_context, 'cc')
        )

    def generate_code(self, definitions, definition_name):
        self.typedef_resolver.resolve(definitions, definition_name)

        # TODO(dglazkov): Implement dictionaries
        if definition_name not in definitions.interfaces:
            return None

        interface = definitions.interfaces[definition_name]
        if WEB_AGENT_API_IDL_ATTRIBUTE not in interface.extended_attributes:
            return None

        return self.generate_interface_code(interface)
