#!/usr/bin/python
#
# Copyright 2017 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.

# This script reads the global interface data collected by
# compute_interfaces_info_overall.py, and writes out the code which adds
# bindings for origin-trial-enabled features at runtime.

import optparse
import os
import posixpath
import sys
from collections import defaultdict, namedtuple

from .code_generator import (initialize_jinja_env, normalize_and_sort_includes,
                            render_template)
from .idl_reader import IdlReader
from .utilities import (create_component_info_provider, write_file,
                       idl_filename_to_component)
from .v8_utilities import (binding_header_basename, v8_class_name,
                          v8_class_name_or_partial, uncapitalize)

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


ConditionalInterfaceInfo = namedtuple('ConditionalInterfaceInfo', [
    'name', 'v8_class', 'v8_class_or_partial', 'is_global'])


def get_install_functions(interfaces, feature_names):
    """Construct a list of V8 bindings installation functions for each feature
    on each interface.

    interfaces is a list of ConditionalInterfaceInfo tuples
    feature_names is a list of strings, containing names of features which can
        be installed on those interfaces.
    """
    return [
        {'condition': 'OriginTrials::%sEnabled' % uncapitalize(feature_name),
         'name': feature_name,
         'install_method': 'install%s' % feature_name,
         'interface_is_global': interface_info.is_global,
         'v8_class': interface_info.v8_class,
         'v8_class_or_partial': interface_info.v8_class_or_partial}
        for feature_name in feature_names
        for interface_info in interfaces]


def get_conditional_feature_names_from_interface(interface):
    feature_names = set()
    if ('OriginTrialEnabled' in interface.extended_attributes and
            interface.is_partial):
        feature_names.add(interface.extended_attributes['OriginTrialEnabled'])
    for operation in interface.operations:
        if 'OriginTrialEnabled' in operation.extended_attributes:
            feature_names.add(
                operation.extended_attributes['OriginTrialEnabled'])
    for attribute in interface.attributes:
        if 'OriginTrialEnabled' in attribute.extended_attributes:
            feature_names.add(
                attribute.extended_attributes['OriginTrialEnabled'])
    return feature_names


def read_idl_file(reader, idl_filename):
    definitions = reader.read_idl_file(idl_filename)
    interfaces = definitions.interfaces
    implements = definitions.implements
    # There should only be a single interface defined in an IDL file. Return it.
    assert len(interfaces) == 1
    return (list(interfaces.values())[0], implements)


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


def conditional_features_info(info_provider, reader, idl_filenames, target_component, snake_case):
    """Read a set of IDL files and compile the mapping between interfaces and
    the conditional features defined on them.

    Returns a tuple (features_for_type, types_for_feature, includes):
      - features_for_type is a mapping of interface->feature
      - types_for_feature is the reverse mapping: feature->interface
      - includes is a set of header files which need to be included in the
          generated implementation code.
    """
    features_for_type = defaultdict(set)
    types_for_feature = defaultdict(set)
    includes = set()

    for idl_filename in idl_filenames:
        interface, implements = read_idl_file(reader, idl_filename)
        feature_names = get_conditional_feature_names_from_interface(interface)

        # If this interface implements another one,
        # it inherits any conditional features from it.
        for implement in implements:
            assert implement.left_interface == interface.name
            implemented_interface, _ = read_idl_file(
                reader,
                info_provider.interfaces_info[implement.right_interface].get('full_path'))
            feature_names |= get_conditional_feature_names_from_interface(implemented_interface)

        feature_names = list(feature_names)
        if feature_names:
            is_global = interface_is_global(interface)
            if interface.is_partial:
                # For partial interfaces, we need to generate different
                # includes if the parent interface is in a different
                # component.
                parent_interface_info = info_provider.interfaces_info[interface.name]
                parent_interface, _ = read_idl_file(
                    reader, parent_interface_info.get('full_path'))
                is_global = is_global or interface_is_global(parent_interface)
                parent_component = idl_filename_to_component(
                    parent_interface_info.get('full_path'))
            if interface.is_partial and target_component != parent_component:
                includes.add('bindings/%s/v8/%s' %
                             (parent_component, binding_header_basename(interface.name, snake_case)))
                includes.add('bindings/%s/v8/%s' %
                             (target_component, binding_header_basename(interface.name + 'Partial', snake_case)))
            else:
                includes.add('bindings/%s/v8/%s' %
                             (target_component, binding_header_basename(interface.name, snake_case)))
                # If this is a partial interface in the same component as
                # its parent, then treat it as a non-partial interface.
                interface.is_partial = False
            interface_info = ConditionalInterfaceInfo(interface.name,
                                                      v8_class_name(interface),
                                                      v8_class_name_or_partial(
                                                          interface),
                                                      is_global)
            for feature_name in feature_names:
                features_for_type[interface_info].add(feature_name)
                types_for_feature[feature_name].add(interface_info)

    return features_for_type, types_for_feature, includes


def conditional_features_context(generator_name, feature_info, snake_case):
    context = {'code_generator': generator_name}

    # Unpack the feature info tuple.
    features_for_type, types_for_feature, includes = feature_info

    # Add includes needed for cpp code and normalize.
    includes.update([
        'core/context_features/ContextFeatureSettings.h',
        'core/dom/ExecutionContext.h',
        'core/frame/Frame.h',
        'core/origin_trials/origin_trials.h',
        'platform/bindings/ConditionalFeatures.h',
        'platform/bindings/ScriptState.h',
        # TODO(iclelland): Remove the need to explicitly include this; it is
        # here because the ContextFeatureSettings code needs it.
        'bindings/core/v8/V8Window.h',
    ])
    context['includes'] = normalize_and_sort_includes(includes, snake_case)

    # For each interface, collect a list of bindings installation functions to
    # call, organized by conditional feature.
    context['installers_by_interface'] = [
        {'name': interface_info.name,
         'is_global': interface_info.is_global,
         'v8_class': interface_info.v8_class,
         'installers': get_install_functions([interface_info], feature_names)}
        for interface_info, feature_names in list(features_for_type.items())]
    context['installers_by_interface'].sort(key=lambda x: x['name'])

    # For each conditional feature, collect a list of bindings installation
    # functions to call, organized by interface.
    context['installers_by_feature'] = [
        {'name': feature_name,
         'name_constant': 'OriginTrials::k%sTrialName' % feature_name,
         'installers': get_install_functions(interfaces, [feature_name])}
        for feature_name, interfaces in list(types_for_feature.items())]
    context['installers_by_feature'].sort(key=lambda x: x['name'])

    return context


def parse_options():
    parser = optparse.OptionParser()
    parser.add_option('--cache-directory',
                      help='cache directory, defaults to output directory')
    parser.add_option('--output-directory')
    parser.add_option('--info-dir')
    parser.add_option('--target-component',
                      type='choice',
                      choices=['Core', 'Modules'],
                      help='target component to generate code')
    parser.add_option('--idl-files-list')
    # TODO(tkent): Remove the option after the great mv. crbug.com/760462
    parser.add_option('--snake-case-generated-files',
                      action='store_true', default=False)

    options, _ = parser.parse_args()
    if options.output_directory is None:
        parser.error('Must specify output directory using --output-directory.')
    return options


def generate_conditional_features(info_provider, options, idl_filenames):
    reader = IdlReader(info_provider.interfaces_info, options.cache_directory)
    jinja_env = initialize_jinja_env(options.cache_directory)

    # Extract the bidirectional mapping of conditional features <-> interfaces
    # from the global info provider and the supplied list of IDL files.
    feature_info = conditional_features_info(info_provider,
                                             reader, idl_filenames,
                                             options.target_component.lower(),
                                             options.snake_case_generated_files)

    # Convert that mapping into the context required for the Jinja2 templates.
    template_context = conditional_features_context(
        MODULE_PYNAME, feature_info, options.snake_case_generated_files)

    # Generate and write out the header file
    header_text = render_template(jinja_env.get_template(
        'ConditionalFeaturesFor%s.h.tmpl' % options.target_component.title()), template_context)
    header_path = posixpath.join(options.output_directory,
                                 'ConditionalFeaturesFor%s.h' % options.target_component.title())
    write_file(header_text, header_path)

    # Generate and write out the implementation file
    cpp_text = render_template(jinja_env.get_template(
        'ConditionalFeaturesFor%s.cpp.tmpl' % options.target_component.title()), template_context)
    cpp_path = posixpath.join(options.output_directory,
                              'ConditionalFeaturesFor%s.cpp' % options.target_component.title())
    write_file(cpp_text, cpp_path)


def main():
    options = parse_options()

    info_provider = create_component_info_provider(
        os.path.normpath(options.info_dir), options.target_component.lower())
    idl_filenames = list(map(str.strip, open(options.idl_files_list)))

    generate_conditional_features(info_provider, options, idl_filenames)
    return 0


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