# Copyright 2014 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Generate Cobalt bindings (.h and .cpp files).

Based on and borrows heavily from code_generator_v8.py which is used as part
of the bindings generation pipeline in Blink.
"""

import abc
from datetime import date
import os
import sys

import bootstrap_path  # pylint: disable=unused-import

from cobalt.bindings import path_generator
from cobalt.bindings.contexts import ContextBuilder
from cobalt.bindings.name_conversion import get_interface_name
from code_generator import CodeGeneratorBase
from code_generator import jinja2
from idl_definitions import IdlTypedef
from idl_types import IdlSequenceType
from idl_types import IdlType

module_path, module_filename = os.path.split(os.path.realpath(__file__))

# Track the cobalt directory, so we can use it for building relative paths.
cobalt_dir = os.path.normpath(os.path.join(module_path, os.pardir))

SHARED_TEMPLATES_DIR = os.path.abspath(os.path.join(module_path, 'templates'))


def initialize_jinja_env(cache_dir, templates_dir):
  """Initialize the Jinja2 environment."""
  assert os.path.isabs(templates_dir)
  assert os.path.isabs(SHARED_TEMPLATES_DIR)
  # Ensure that we are using the version of jinja that's checked in to
  # third_party.
  assert jinja2.__version__ == '2.7.1'
  jinja_env = jinja2.Environment(
      loader=jinja2.FileSystemLoader([templates_dir, SHARED_TEMPLATES_DIR]),
      extensions=['jinja2.ext.do'],  # do statement
      # Bytecode cache is not concurrency-safe unless pre-cached:
      # if pre-cached this is read-only, but writing creates a race condition.
      bytecode_cache=jinja2.FileSystemBytecodeCache(cache_dir),
      keep_trailing_newline=True,  # newline-terminate generated files
      lstrip_blocks=True,  # so can indent control flow tags
      trim_blocks=True)
  return jinja_env


def normalize_slashes(path):
  if os.path.sep == '\\':
    return path.replace('\\', '/')
  else:
    return path


def is_global_interface(interface):
  return (('PrimaryGlobal' in interface.extended_attributes) or
          ('Global' in interface.extended_attributes))


def get_indexed_special_operation(interface, special):
  special_operations = list(
      operation for operation in interface.operations
      if (special in operation.specials and operation.arguments and
          str(operation.arguments[0].idl_type) == 'unsigned long'))
  assert len(special_operations) <= 1, (
      'Multiple indexed %ss defined on interface: %s' % (special,
                                                         interface.name))
  return special_operations[0] if len(special_operations) else None


def get_indexed_property_getter(interface):
  getter_operation = get_indexed_special_operation(interface, 'getter')
  assert not getter_operation or len(getter_operation.arguments) == 1
  return getter_operation


def get_indexed_property_setter(interface):
  setter_operation = get_indexed_special_operation(interface, 'setter')
  assert not setter_operation or len(setter_operation.arguments) == 2
  return setter_operation


def get_indexed_property_deleter(interface):
  deleter_operation = get_indexed_special_operation(interface, 'deleter')
  assert not deleter_operation or len(deleter_operation.arguments) == 1
  return deleter_operation


def get_named_special_operation(interface, special):
  special_operations = list(
      operation for operation in interface.operations
      if (special in operation.specials and operation.arguments and
          str(operation.arguments[0].idl_type) == 'DOMString'))
  assert len(special_operations) <= 1, (
      'Multiple named %ss defined on interface: %s' % (special, interface.name))
  return special_operations[0] if len(special_operations) else None


def get_named_property_getter(interface):
  getter_operation = get_named_special_operation(interface, 'getter')
  assert not getter_operation or len(getter_operation.arguments) == 1
  return getter_operation


def get_named_property_setter(interface):
  setter_operation = get_named_special_operation(interface, 'setter')
  assert not setter_operation or len(setter_operation.arguments) == 2
  return setter_operation


def get_named_property_deleter(interface):
  deleter_operation = get_named_special_operation(interface, 'deleter')
  assert not deleter_operation or len(deleter_operation.arguments) == 1
  return deleter_operation


def get_interface_type_names_from_idl_types(info_provider, idl_type_list):
  for idl_type in idl_type_list:
    if idl_type:
      idl_type = idl_type.resolve_typedefs(info_provider.typedefs)
      if isinstance(idl_type, IdlTypedef):
        idl_type = idl_type.idl_type

      if idl_type.is_interface_type:
        yield get_interface_name(idl_type)
      if idl_type.is_dictionary:
        yield idl_type.name
      elif idl_type.is_union_type:
        for interface_name in get_interface_type_names_from_idl_types(
            info_provider, idl_type.member_types):
          yield interface_name
      elif idl_type.is_enum:
        yield idl_type.name
      elif isinstance(idl_type, IdlSequenceType):
        for interface_name in get_interface_type_names_from_idl_types(
            info_provider, [idl_type.element_type]):
          yield interface_name


def get_interface_type_names_from_typed_objects(info_provider,
                                                typed_object_list):
  for typed_object in typed_object_list:
    for interface_name in get_interface_type_names_from_idl_types(
        info_provider, [typed_object.idl_type]):
      yield interface_name

    if hasattr(typed_object, 'arguments'):
      for interface_name in get_interface_type_names_from_typed_objects(
          info_provider, typed_object.arguments):
        yield interface_name


def split_unsupported_properties(context_list):
  supported = []
  unsupported = []
  for context in context_list:
    if context['unsupported']:
      unsupported.append(context['idl_name'])
    else:
      supported.append(context)
  return supported, unsupported


class CodeGeneratorCobalt(CodeGeneratorBase):
  """Abstract Base code generator class for Cobalt.

  Concrete classes will provide an implementation for generating bindings for a
  specific JavaScript engine implementation.
  """
  __metaclass__ = abc.ABCMeta

  def __init__(self, templates_dir, info_provider, cache_dir, output_dir):
    super(CodeGeneratorCobalt, self).__init__(
        'CodeGeneratorCobalt', info_provider, cache_dir, output_dir)
    # CodeGeneratorBase inititalizes this with the v8 template path, so
    # reinitialize it with cobalt's template path

    # Whether the path is absolute or relative affects the cache file name. Use
    # the absolute path to ensure that we use the same path as was used when the
    # cache was prepopulated.
    self.jinja_env = initialize_jinja_env(cache_dir,
                                          os.path.abspath(templates_dir))
    self.path_builder = path_generator.PathBuilder(
        self.generated_file_prefix, self.info_provider, cobalt_dir, output_dir)

  @abc.abstractproperty
  def generated_file_prefix(self):
    """The prefix to prepend to all generated source files."""
    pass

  @abc.abstractproperty
  def expression_generator(self):
    """An instance that implements the ExpressionGenerator class."""
    pass

  def render_template(self, template_filename, template_context):
    template = self.jinja_env.get_template(template_filename)
    template_context.update(self.common_context(template))
    rendered_text = template.render(template_context)
    return rendered_text

  def generate_code(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])
    if definition_name in definitions.enumerations:
      return self.generate_enum_code(definitions, definition_name,
                                     definitions.enumerations[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]
    # Select appropriate Jinja template and contents function
    if interface.is_callback:
      header_template_filename = 'callback-interface.h.template'
      cpp_template_filename = 'callback-interface.cc.template'
    elif interface.is_partial:
      raise NotImplementedError('Partial interfaces not implemented')
    else:
      header_template_filename = 'interface.h.template'
      cpp_template_filename = 'interface.cc.template'

    template_context = self.build_interface_context(interface, interface_info,
                                                    definitions)
    header_text = self.render_template(header_template_filename,
                                       template_context)
    cc_text = self.render_template(cpp_template_filename, template_context)
    header_path = self.path_builder.BindingsHeaderFullPath(interface_name)
    cc_path = self.path_builder.BindingsImplementationPath(interface_name)
    return ((header_path, header_text), (cc_path, cc_text),)

  def generate_dictionary_code(self, definitions, dictionary_name, dictionary):
    header_template_filename = 'dictionary.h.template'
    conversion_template_filename = 'dictionary-conversion.cc.template'
    implementation_context = self.build_dictionary_context(
        dictionary, definitions, False)
    conversion_context = self.build_dictionary_context(dictionary, definitions,
                                                       True)

    header_text = self.render_template(header_template_filename,
                                       implementation_context)
    conversion_text = self.render_template(conversion_template_filename,
                                           conversion_context)

    header_path = self.path_builder.DictionaryHeaderFullPath(dictionary_name)
    conversion_impl_path = (
        self.path_builder.DictionaryConversionImplementationPath(
            dictionary_name))
    return ((header_path, header_text), (conversion_impl_path,
                                         conversion_text),)

  def generate_enum_code(self, definitions, enumeration_name, enumeration):
    header_template_filename = 'enumeration.h.template'
    conversion_template_filename = 'enumeration-conversion.cc.template'
    context_builder = ContextBuilder(self.info_provider)
    context = context_builder.enumeration_context(enumeration)

    context['components'] = self.path_builder.NamespaceComponents(
        enumeration_name)
    context['namespace'] = self.path_builder.Namespace(enumeration_name)
    context['fully_qualified_name'] = self.path_builder.FullClassName(
        enumeration_name)
    context['enum_include'] = self.path_builder.EnumHeaderIncludePath(
        enumeration_name)

    header_text = self.render_template(header_template_filename, context)
    conversion_text = self.render_template(conversion_template_filename,
                                           context)

    header_path = self.path_builder.EnumHeaderFullPath(enumeration_name)
    conversion_impl_path = (
        self.path_builder.EnumConversionImplementationFullPath(enumeration_name)
    )
    return ((header_path, header_text), (conversion_impl_path,
                                         conversion_text),)

  def generate_conversion_code(self):
    enumerations = list(self.info_provider.enumerations.keys())
    dictionaries = list(self.info_provider.interfaces_info['dictionaries'])
    includes = [
        self.path_builder.DictionaryHeaderIncludePath(dictionary)
        for dictionary in dictionaries
    ]
    includes.extend([
        self.path_builder.EnumHeaderIncludePath(enum) for enum in enumerations
    ])

    context = {
        'dictionaries': self.referenced_class_contexts(dictionaries, False),
        'enumerations': self.referenced_class_contexts(enumerations, False),
        'includes': includes,
    }

    header_template_filename = 'generated-types.h.template'
    header_text = self.render_template(header_template_filename, context)

    return self.path_builder.generated_conversion_header_path, header_text

  def referenced_dictionary_context(self, dictionary_name, dictionary_info):
    namespace = '::'.join(
        self.path_builder.NamespaceComponents(dictionary_name))

    return {
        'fully_qualified_name':
            '%s::%s' % (namespace, dictionary_name),
        'include':
            self.path_builder.DictionaryHeaderIncludePath(dictionary_name),
        'conditional':
            dictionary_info['conditional'],
        'is_callback_interface':
            False,
    }

  def referenced_enum_context(self, enum_name):
    namespace = '::'.join(self.path_builder.NamespaceComponents(enum_name))
    return {
        'fully_qualified_name': '%s::%s' % (namespace, enum_name),
        'include': self.path_builder.EnumHeaderIncludePath(enum_name),
        'conditional': None,
        'is_callback_interface': False,
    }

  def referenced_class_contexts(self,
                                interface_names,
                                include_bindings_class=True):
    """Returns a list of jinja contexts describing referenced C++ classes.

    Args:
      interface_names: A list of interfaces.
      include_bindings_class: Include headers and classes uses only in bindings.
    Returns:
      list() of jinja contexts (python dicts) with information about C++ classes
      related to the interfaces in |interface_names|. dict has the following
      keys:
          fully_qualified_name: Fully qualified name of the class.
          include: Path to the header that defines the class.
          conditional: Symbol on which this interface is conditional compiled.
          is_callback_interface: True iff this is a callback interface.
    """
    referenced_classes = []
    # Iterate over it as a set to uniquify the list.
    for interface_name in set(interface_names):
      if interface_name in self.info_provider.enumerations:
        # If this is an enumeration, get the enum context and continue.
        referenced_classes.append(self.referenced_enum_context(interface_name))
        continue

      interface_info = self.info_provider.interfaces_info[interface_name]
      if interface_info['is_dictionary']:
        referenced_classes.append(
            self.referenced_dictionary_context(interface_name, interface_info))
      else:
        namespace = '::'.join(
            self.path_builder.NamespaceComponents(interface_name))
        conditional = interface_info['conditional']
        is_callback_interface = interface_name in IdlType.callback_interfaces
        referenced_classes.append({
            'fully_qualified_name':
                '%s::%s' % (namespace, interface_name),
            'include':
                self.path_builder.ImplementationHeaderPath(interface_name),
            'conditional':
                conditional,
            'is_callback_interface':
                is_callback_interface,
        })
        if include_bindings_class:
          referenced_classes.append({
              'fully_qualified_name':
                  '%s::%s' % (namespace,
                              self.path_builder.BindingsClass(interface_name)),
              'include':
                  self.path_builder.BindingsHeaderIncludePath(interface_name),
              'conditional':
                  conditional,
              'is_callback_interface':
                  is_callback_interface,
          })
    return referenced_classes

  def common_context(self, template):
    """Shared stuff."""
    # Make sure extension is .py, not .pyc or .pyo, so doesn't depend on caching
    module_path_pyname = os.path.join(
        module_path, os.path.splitext(module_filename)[0] + '.py')

    # Ensure that posix forward slashes are used
    context = {
        'today':
            date.today(),
        'code_generator':
            normalize_slashes(os.path.relpath(module_path_pyname, cobalt_dir)),
        'template_path':
            normalize_slashes(os.path.relpath(template.filename, cobalt_dir)),
        'generated_conversion_include':
            self.path_builder.generated_conversion_include_path,
    }
    return context

  def build_dictionary_context(self, dictionary, definitions, for_conversion):
    context_builder = ContextBuilder(self.info_provider)
    context = {
        'class_name':
            dictionary.name,
        'header_file':
            self.path_builder.DictionaryHeaderIncludePath(dictionary.name),
        'members': [
            context_builder.get_dictionary_member_context(dictionary, member)
            for member in dictionary.members
        ]
    }
    referenced_interface_names = set(
        get_interface_type_names_from_typed_objects(self.info_provider,
                                                    dictionary.members))
    if dictionary.parent:
      referenced_interface_names.add(dictionary.parent)
      context['parent'] = dictionary.parent

    referenced_class_contexts = self.referenced_class_contexts(
        referenced_interface_names, for_conversion)

    context['includes'] = sorted(interface['include']
                                 for interface in referenced_class_contexts)
    context['forward_declarations'] = sorted(
        referenced_class_contexts, key=lambda x: x['fully_qualified_name'])
    context['components'] = self.path_builder.NamespaceComponents(
        dictionary.name)
    return context

  def build_interface_context(self, interface, interface_info, definitions):
    context_builder = ContextBuilder(self.info_provider)

    context = {
        # Parameters used for template rendering.
        'today':
            date.today(),
        'binding_class':
            self.path_builder.BindingsClass(interface.name),
        'fully_qualified_binding_class':
            self.path_builder.FullBindingsClassName(interface.name),
        'header_file':
            self.path_builder.BindingsHeaderIncludePath(interface.name),
        'impl_class':
            interface.name,
        'fully_qualified_impl_class':
            self.path_builder.FullClassName(interface.name),
        'interface_name':
            interface.name,
        'is_global_interface':
            is_global_interface(interface),
        'has_interface_object': (
            'NoInterfaceObject' not in interface.extended_attributes),
        'conditional':
            interface.extended_attributes.get('Conditional', None),
    }
    interfaces_info = self.info_provider.interfaces_info
    if is_global_interface(interface):
      # Global interface references all interfaces.
      referenced_interface_names = set(
          interface_name for interface_name in interfaces_info['all_interfaces']
          if not interfaces_info[interface_name]['unsupported'] and
          not interfaces_info[interface_name]['is_callback_interface'] and
          not interfaces_info[interface_name]['is_dictionary'])
      referenced_interface_names.update(IdlType.callback_interfaces)
    else:
      # Build the set of referenced interfaces from this interface's members.
      referenced_interface_names = set()
      referenced_interface_names.update(
          get_interface_type_names_from_typed_objects(self.info_provider,
                                                      interface.attributes))
      referenced_interface_names.update(
          get_interface_type_names_from_typed_objects(self.info_provider,
                                                      interface.operations))
      referenced_interface_names.update(
          get_interface_type_names_from_typed_objects(self.info_provider,
                                                      interface.constructors))
      referenced_interface_names.update(
          get_interface_type_names_from_typed_objects(
              self.info_provider, definitions.callback_functions.values()))

    # Build the set of #includes in the header file. Try to keep this small
    # to avoid circular dependency problems.
    header_includes = set()
    if interface.parent:
      header_includes.add(
          self.path_builder.BindingsHeaderIncludePath(interface.parent))
      referenced_interface_names.add(interface.parent)
    header_includes.add(
        self.path_builder.ImplementationHeaderPath(interface.name))

    attributes = [
        context_builder.attribute_context(interface, attribute, definitions)
        for attribute in interface.attributes
    ]
    constructor = context_builder.get_constructor_context(
        self.expression_generator, interface)
    methods = context_builder.get_method_contexts(self.expression_generator,
                                                  interface)
    constants = [
        context_builder.constant_context(c) for c in interface.constants
    ]

    # Get a list of all the unsupported property names, and remove the
    # unsupported ones from their respective lists
    attributes, unsupported_attribute_names = split_unsupported_properties(
        attributes)
    methods, unsupported_method_names = split_unsupported_properties(methods)
    constants, unsupported_constant_names = split_unsupported_properties(
        constants)

    # Build a set of all interfaces referenced by this interface.
    referenced_class_contexts = self.referenced_class_contexts(
        referenced_interface_names)

    all_interfaces = []
    for interface_name in referenced_interface_names:
      if (interface_name not in IdlType.callback_interfaces and
          interface_name not in IdlType.enums and
          not interfaces_info[interface_name]['unsupported'] and
          not interfaces_info[interface_name]['is_dictionary']):
        all_interfaces.append({
            'name': interface_name,
            'conditional': interfaces_info[interface_name]['conditional'],
        })

    context['implementation_includes'] = sorted(
        (interface['include'] for interface in referenced_class_contexts))
    context['header_includes'] = sorted(header_includes)
    context['attributes'] = [a for a in attributes if not a['is_static']]
    context['static_attributes'] = [a for a in attributes if a['is_static']]
    context['constants'] = constants
    context['constructor'] = constructor
    context['named_constructor'] = interface.extended_attributes.get(
        'NamedConstructor', None)
    context['interface'] = interface
    context['operations'] = [m for m in methods if not m['is_static']]
    context['static_operations'] = [m for m in methods if m['is_static']]
    context['unsupported_interface_properties'] = set(
        unsupported_attribute_names + unsupported_method_names +
        unsupported_constant_names)
    context['unsupported_constructor_properties'] = set(
        unsupported_constant_names)
    if interface.parent:
      context['parent_interface'] = self.path_builder.BindingsClass(
          interface.parent)
    context['is_exception_interface'] = interface.is_exception
    context['forward_declarations'] = sorted(
        referenced_class_contexts, key=lambda x: x['fully_qualified_name'])
    context['all_interfaces'] = sorted(all_interfaces, key=lambda x: x['name'])
    context['callback_functions'] = definitions.callback_functions.values()
    context['enumerations'] = [
        context_builder.enumeration_context(enumeration)
        for enumeration in definitions.enumerations.values()
    ]
    context['components'] = self.path_builder.NamespaceComponents(
        interface.name)

    context['stringifier'] = context_builder.stringifier_context(interface)
    context['indexed_property_getter'] = context_builder.special_method_context(
        interface, get_indexed_property_getter(interface))
    context['indexed_property_setter'] = context_builder.special_method_context(
        interface, get_indexed_property_setter(interface))
    context[
        'indexed_property_deleter'] = context_builder.special_method_context(
            interface, get_indexed_property_deleter(interface))
    context['named_property_getter'] = context_builder.special_method_context(
        interface, get_named_property_getter(interface))
    context['named_property_setter'] = context_builder.special_method_context(
        interface, get_named_property_setter(interface))
    context['named_property_deleter'] = context_builder.special_method_context(
        interface, get_named_property_deleter(interface))

    context['supports_indexed_properties'] = (
        context['indexed_property_getter'] or
        context['indexed_property_setter'])
    context['supports_named_properties'] = (context['named_property_setter'] or
                                            context['named_property_getter'] or
                                            context['named_property_deleter'])

    return context


################################################################################


def main(argv):
  # If file itself executed, cache templates
  try:
    cache_dir = argv[1]
    templates_dir = argv[2]
    dummy_filename = argv[3]
  except IndexError:
    print 'Usage: %s CACHE_DIR TEMPLATES_DIR DUMMY_FILENAME' % argv[0]
    return 1

  # Delete all jinja2 .cache files, since they will get regenerated anyways.
  for filename in os.listdir(cache_dir):
    if os.path.splitext(filename)[1] == '.cache':
      # We expect that the only .cache files in this directory are for jinja2
      # and they have a __jinja2_ prefix.
      assert filename.startswith('__jinja2_')
      os.remove(os.path.join(cache_dir, filename))

  # Cache templates.
  # Whether the path is absolute or relative affects the cache file name. Use
  # the absolute path to ensure that the same path is used when we populate the
  # cache here and when it's read during code generation.
  jinja_env = initialize_jinja_env(cache_dir, os.path.abspath(templates_dir))
  template_filenames = [
      filename
      for filename in os.listdir(templates_dir)
      # Skip .svn, directories, etc.
      if filename.endswith(('.template'))
  ]
  assert template_filenames, 'Expected at least one template to be cached.'
  shared_template_filenames = [
      filename
      for filename in os.listdir(SHARED_TEMPLATES_DIR)
      # Skip .svn, directories, etc.
      if filename.endswith(('.template'))
  ]
  for template_filename in template_filenames + shared_template_filenames:
    jinja_env.get_template(template_filename)

  # Create a dummy file as output for the build system,
  # since filenames of individual cache files are unpredictable and opaque
  # (they are hashes of the template path, which varies based on environment)
  with open(dummy_filename, 'w') as dummy_file:
    pass  # |open| creates or touches the file


if __name__ == '__main__':
  sys.exit(main(sys.argv))
