# 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.

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

"""Generate Blink V8 bindings (.h and .cpp files).

If run itself, caches Jinja templates (and creates dummy file for build,
since cache filenames are unpredictable and opaque).

This module is *not* concurrency-safe without care: bytecode caching creates
a race condition on cache *write* (crashes if one process tries to read a
partially-written cache). However, if you pre-cache the templates (by running
the module itself), then you can parallelize compiling individual files, since
cache *reading* is safe.

Input: An object of class IdlDefinitions, containing an IDL interface X
Output: V8X.h and V8X.cpp

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

import os
import posixpath

from .code_generator import CodeGeneratorBase, render_template, normalize_and_sort_includes
from .idl_definitions import Visitor
from .idl_types import IdlType
from . import v8_callback_function
from . import v8_callback_interface
from . import v8_dictionary
from .v8_globals import includes
from . import v8_interface
from . import v8_types
from . import v8_union
from .v8_utilities import build_basename, cpp_name
from .utilities import idl_filename_to_component, is_testing_target, shorten_union_name, to_snake_case


# Make sure extension is .py, not .pyc or .pyo, so doesn't depend on caching
MODULE_PYNAME = os.path.splitext(os.path.basename(__file__))[0] + '.py'

def depending_union_type(idl_type):
    """Returns the union type name if the given idl_type depends on a
    union type.
    """
    def find_base_type(current_type):
        if current_type.is_array_or_sequence_type:
            return find_base_type(current_type.element_type)
        if current_type.is_record_type:
            # IdlRecordType.key_type is always a string type, so we only need
            # to looking into value_type.
            return find_base_type(current_type.value_type)
        if current_type.is_nullable:
            return find_base_type(current_type.inner_type)
        return current_type
    base_type = find_base_type(idl_type)
    if base_type.is_union_type:
        return base_type
    return None


class TypedefResolver(Visitor):
    def __init__(self, info_provider):
        self.info_provider = info_provider
        self.additional_header_includes = set()
        self.typedefs = {}

    def resolve(self, definitions, definition_name):
        """Traverse definitions and resolves typedefs with the actual types."""
        self.typedefs = {}
        for name, typedef in self.info_provider.typedefs.items():
            self.typedefs[name] = typedef.idl_type
        self.additional_header_includes = set()
        definitions.accept(self)
        self._update_dependencies_include_paths(definition_name)

    def _update_dependencies_include_paths(self, definition_name):
        if definition_name not in self.info_provider.interfaces_info:
            return
        interface_info = self.info_provider.interfaces_info[definition_name]
        interface_info['additional_header_includes'] = set(
            self.additional_header_includes)

    def _resolve_typedefs(self, typed_object):
        """Resolve typedefs to actual types in the object."""
        for attribute_name in typed_object.idl_type_attributes:
            try:
                idl_type = getattr(typed_object, attribute_name)
            except AttributeError:
                continue
            if not idl_type:
                continue
            resolved_idl_type = idl_type.resolve_typedefs(self.typedefs)
            # TODO(bashi): Dependency resolution shouldn't happen here.
            # Move this into includes_for_type() families.
            union_type = depending_union_type(resolved_idl_type)
            if union_type:
                self.additional_header_includes.add(
                    self.info_provider.include_path_for_union_types(union_type))
            # Need to re-assign the attribute, not just mutate idl_type, since
            # type(idl_type) may change.
            setattr(typed_object, attribute_name, resolved_idl_type)

    def visit_typed_object(self, typed_object):
        self._resolve_typedefs(typed_object)


class CodeGeneratorV8Base(CodeGeneratorBase):
    """Base class for v8 bindings generator and IDL dictionary impl generator"""

    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.typedef_resolver = TypedefResolver(info_provider)

    def generate_code(self, definitions, definition_name):
        """Returns .h/.cpp code as ((path, content)...)."""
        # Set local type info
        if not self.should_generate_code(definitions):
            return set()

        # Resolve typedefs
        self.typedef_resolver.resolve(definitions, definition_name)
        return self.generate_code_internal(definitions, definition_name)

    def generate_code_internal(self, definitions, definition_name):
        # This should be implemented in subclasses.
        raise NotImplementedError()

    def get_output_basename(self, definition_name, ext, prefix=None):
        return build_basename(definition_name, self.snake_case_generated_files, prefix=prefix, ext=ext)


class CodeGeneratorV8(CodeGeneratorV8Base):
    def __init__(self, info_provider, cache_dir, output_dir, snake_case):
        CodeGeneratorV8Base.__init__(self, info_provider, cache_dir, output_dir, snake_case)

    def output_paths(self, definition_name):
        header_path = posixpath.join(self.output_dir, self.get_output_basename(
            definition_name, '.h', prefix='V8'))
        cpp_path = posixpath.join(self.output_dir, self.get_output_basename(
            definition_name, '.cpp', prefix='V8'))
        return header_path, cpp_path

    def generate_code_internal(self, definitions, definition_name):
        if definition_name in definitions.interfaces:
            return self.generate_interface_code(
                definitions, definition_name,
                definitions.interfaces[definition_name])
        if definition_name in definitions.dictionaries:
            return self.generate_dictionary_code(
                definitions, definition_name,
                definitions.dictionaries[definition_name])
        raise ValueError('%s is not in IDL definitions' % definition_name)

    def generate_interface_code(self, definitions, interface_name, interface):
        interface_info = self.info_provider.interfaces_info[interface_name]
        full_path = interface_info.get('full_path')
        component = idl_filename_to_component(full_path)
        include_paths = interface_info.get('dependencies_include_paths')

        # Select appropriate Jinja template and contents function
        #
        # A callback interface with constants needs a special handling.
        # https://heycam.github.io/webidl/#legacy-callback-interface-object
        if interface.is_callback and len(interface.constants) > 0:
            header_template_filename = 'legacy_callback_interface.h.tmpl'
            cpp_template_filename = 'legacy_callback_interface.cpp.tmpl'
            interface_context = v8_callback_interface.legacy_callback_interface_context
        elif interface.is_callback:
            header_template_filename = 'callback_interface.h.tmpl'
            cpp_template_filename = 'callback_interface.cpp.tmpl'
            interface_context = v8_callback_interface.callback_interface_context
        elif interface.is_partial:
            interface_context = v8_interface.interface_context
            header_template_filename = 'partial_interface.h.tmpl'
            cpp_template_filename = 'partial_interface.cpp.tmpl'
            interface_name += 'Partial'
            assert component == 'core'
            component = 'modules'
            include_paths = interface_info.get('dependencies_other_component_include_paths')
        else:
            header_template_filename = 'interface.h.tmpl'
            cpp_template_filename = 'interface.cpp.tmpl'
            interface_context = v8_interface.interface_context

        template_context = interface_context(interface, definitions.interfaces)
        includes.update(interface_info.get('cpp_includes', {}).get(component, set()))
        if not interface.is_partial and not is_testing_target(full_path):
            template_context['header_includes'].add(self.info_provider.include_path_for_export)
            template_context['exported'] = self.info_provider.specifier_for_export
        # Add the include for interface itself
        if IdlType(interface_name).is_typed_array:
            template_context['header_includes'].add('core/typed_arrays/DOMTypedArray.h')
        else:
            template_context['header_includes'].add(interface_info['include_path'])
        template_context['header_includes'].update(
            interface_info.get('additional_header_includes', []))
        header_path, cpp_path = self.output_paths(interface_name)
        template_context['this_include_header_name'] = posixpath.basename(header_path)
        header_template = self.jinja_env.get_template(header_template_filename)
        cpp_template = self.jinja_env.get_template(cpp_template_filename)
        header_text, cpp_text = self.render_template(
            include_paths, header_template, cpp_template, template_context,
            component)
        return (
            (header_path, header_text),
            (cpp_path, cpp_text),
        )

    def generate_dictionary_code(self, definitions, dictionary_name,
                                 dictionary):
        # pylint: disable=unused-argument
        interfaces_info = self.info_provider.interfaces_info
        header_template = self.jinja_env.get_template('dictionary_v8.h.tmpl')
        cpp_template = self.jinja_env.get_template('dictionary_v8.cpp.tmpl')
        interface_info = interfaces_info[dictionary_name]
        template_context = v8_dictionary.dictionary_context(
            dictionary, interfaces_info)
        include_paths = interface_info.get('dependencies_include_paths')
        # Add the include for interface itself
        template_context['header_includes'].add(interface_info['include_path'])
        if not is_testing_target(interface_info.get('full_path')):
            template_context['header_includes'].add(self.info_provider.include_path_for_export)
            template_context['exported'] = self.info_provider.specifier_for_export
        header_path, cpp_path = self.output_paths(dictionary_name)
        template_context['this_include_header_name'] = posixpath.basename(header_path)
        header_text, cpp_text = self.render_template(
            include_paths, header_template, cpp_template, template_context)
        return (
            (header_path, header_text),
            (cpp_path, cpp_text),
        )


class CodeGeneratorDictionaryImpl(CodeGeneratorV8Base):
    def __init__(self, info_provider, cache_dir, output_dir, snake_case):
        CodeGeneratorV8Base.__init__(self, info_provider, cache_dir, output_dir, snake_case)

    def output_paths(self, definition_name, interface_info):
        output_dir = posixpath.join(self.output_dir,
                                    interface_info['relative_dir'])
        header_path = posixpath.join(output_dir,
                                     self.get_output_basename(definition_name, '.h'))
        cpp_path = posixpath.join(output_dir,
                                  self.get_output_basename(definition_name, '.cpp'))
        return header_path, cpp_path

    def generate_code_internal(self, definitions, definition_name):
        if not definition_name in definitions.dictionaries:
            raise ValueError('%s is not an IDL dictionary' % definition_name)
        interfaces_info = self.info_provider.interfaces_info
        dictionary = definitions.dictionaries[definition_name]
        interface_info = interfaces_info[definition_name]
        header_template = self.jinja_env.get_template('dictionary_impl.h.tmpl')
        cpp_template = self.jinja_env.get_template('dictionary_impl.cpp.tmpl')
        template_context = v8_dictionary.dictionary_impl_context(
            dictionary, interfaces_info)
        include_paths = interface_info.get('dependencies_include_paths')
        if not is_testing_target(interface_info.get('full_path')):
            template_context['exported'] = self.info_provider.specifier_for_export
            template_context['header_includes'].add(self.info_provider.include_path_for_export)
        template_context['header_includes'].update(
            interface_info.get('additional_header_includes', []))
        header_path, cpp_path = self.output_paths(
            cpp_name(dictionary), interface_info)
        template_context['this_include_header_name'] = posixpath.basename(header_path)
        header_text, cpp_text = self.render_template(
            include_paths, header_template, cpp_template, template_context)
        return (
            (header_path, header_text),
            (cpp_path, cpp_text),
        )


class CodeGeneratorUnionType(CodeGeneratorBase):
    """Generates union type container classes.
    This generator is different from CodeGeneratorV8 and
    CodeGeneratorDictionaryImpl. It assumes that all union types are already
    collected. It doesn't process idl files directly.
    """
    def __init__(self, info_provider, cache_dir, output_dir, snake_case, target_component):
        CodeGeneratorBase.__init__(self, MODULE_PYNAME, info_provider, cache_dir, output_dir, snake_case)
        self.target_component = target_component
        # The code below duplicates parts of TypedefResolver. We do not use it
        # directly because IdlUnionType is not a type defined in
        # idl_definitions.py. What we do instead is to resolve typedefs in
        # _generate_container_code() whenever a new union file is generated.
        self.typedefs = {}
        for name, typedef in self.info_provider.typedefs.items():
            self.typedefs[name] = typedef.idl_type

    def _generate_container_code(self, union_type):
        union_type = union_type.resolve_typedefs(self.typedefs)
        header_template = self.jinja_env.get_template('union_container.h.tmpl')
        cpp_template = self.jinja_env.get_template('union_container.cpp.tmpl')
        template_context = v8_union.container_context(
            union_type, self.info_provider)
        template_context['header_includes'].append(
            self.info_provider.include_path_for_export)
        template_context['header_includes'] = normalize_and_sort_includes(
            template_context['header_includes'], self.snake_case_generated_files)
        template_context['cpp_includes'] = normalize_and_sort_includes(
            template_context['cpp_includes'], self.snake_case_generated_files)
        template_context['code_generator'] = self.generator_name
        template_context['exported'] = self.info_provider.specifier_for_export
        snake_base_name = to_snake_case(shorten_union_name(union_type))
        template_context['this_include_header_name'] = snake_base_name
        header_text = render_template(header_template, template_context)
        cpp_text = render_template(cpp_template, template_context)
        header_path = posixpath.join(self.output_dir, '%s.h' % snake_base_name)
        cpp_path = posixpath.join(self.output_dir, '%s.cc' % snake_base_name)
        return (
            (header_path, header_text),
            (cpp_path, cpp_text),
        )

    def _get_union_types_for_containers(self):
        union_types = self.info_provider.union_types
        if not union_types:
            return None
        # For container classes we strip nullable wrappers. For example,
        # both (A or B)? and (A? or B) will become AOrB. This should be OK
        # because container classes can handle null and it seems that
        # distinguishing (A or B)? and (A? or B) doesn't make sense.
        container_cpp_types = set()
        union_types_for_containers = set()
        for union_type in union_types:
            cpp_type = union_type.cpp_type
            if cpp_type not in container_cpp_types:
                union_types_for_containers.add(union_type)
                container_cpp_types.add(cpp_type)
        return union_types_for_containers

    def generate_code(self):
        union_types = self._get_union_types_for_containers()
        if not union_types:
            return ()
        outputs = set()
        for union_type in union_types:
            outputs.update(self._generate_container_code(union_type))
        return outputs


class CodeGeneratorCallbackFunction(CodeGeneratorBase):
    def __init__(self, info_provider, cache_dir, output_dir, snake_case, target_component):
        CodeGeneratorBase.__init__(self, MODULE_PYNAME, info_provider, cache_dir, output_dir, snake_case)
        self.target_component = target_component
        self.typedef_resolver = TypedefResolver(info_provider)

    def generate_code_internal(self, callback_function, path):
        self.typedef_resolver.resolve(callback_function, callback_function.name)
        header_template = self.jinja_env.get_template('callback_function.h.tmpl')
        cpp_template = self.jinja_env.get_template('callback_function.cpp.tmpl')
        template_context = v8_callback_function.callback_function_context(
            callback_function)
        if not is_testing_target(path):
            template_context['exported'] = self.info_provider.specifier_for_export
            template_context['header_includes'].append(
                self.info_provider.include_path_for_export)
        template_context['header_includes'] = normalize_and_sort_includes(
            template_context['header_includes'], self.snake_case_generated_files)
        template_context['cpp_includes'] = normalize_and_sort_includes(
            template_context['cpp_includes'], self.snake_case_generated_files)
        template_context['code_generator'] = MODULE_PYNAME
        header_text = render_template(header_template, template_context)
        cpp_text = render_template(cpp_template, template_context)
        snake_base_name = to_snake_case('V8%s' % callback_function.name)
        header_path = posixpath.join(self.output_dir, '%s.h' % snake_base_name)
        cpp_path = posixpath.join(self.output_dir, '%s.cc' % snake_base_name)
        return (
            (header_path, header_text),
            (cpp_path, cpp_text),
        )

    # pylint: disable=W0221
    def generate_code(self):
        callback_functions = self.info_provider.callback_functions
        if not callback_functions:
            return ()
        outputs = set()
        for callback_function_dict in callback_functions.values():
            if callback_function_dict['component_dir'] != self.target_component:
                continue
            callback_function = callback_function_dict['callback_function']
            if 'Custom' in callback_function.extended_attributes:
                continue
            path = callback_function_dict['full_path']
            outputs.update(self.generate_code_internal(callback_function, path))
        return outputs
