#!/usr/bin/env python3
# Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.

import database
import databasebuilder
import idlnode
import logging.config
import os.path
import sys
import time
import utilities
import dependency
from idlnode import IDLType, resolveTypedef

_logger = logging.getLogger('fremontcutbuilder')

# See:
#  http://src.chromium.org/viewvc/multivm/trunk/webkit/Source/core/features.gypi
# for ENABLE_* flags defined in Chromium / Blink.
# We list all ENABLE flags used in IDL in one of these two lists.
FEATURE_DISABLED = [
    'ENABLE_CUSTOM_SCHEME_HANDLER',
    'ENABLE_MEDIA_CAPTURE',  # Only enabled on Android.
    'ENABLE_ORIENTATION_EVENTS',  # Only enabled on Android.
    'ENABLE_WEBVTT_REGIONS',
]

FEATURE_DEFINES = [
    'ENABLE_CALENDAR_PICKER',  # Not on Android
    'ENABLE_ENCRYPTED_MEDIA_V2',
    'ENABLE_INPUT_SPEECH',  # Not on Android
    'ENABLE_LEGACY_NOTIFICATIONS',  # Not on Android
    'ENABLE_NAVIGATOR_CONTENT_UTILS',  # Not on Android
    'ENABLE_NOTIFICATIONS',  # Not on Android
    'ENABLE_SVG_FONTS',
    'ENABLE_WEB_AUDIO',  # Not on Android
]


# Resolve all typedefs encountered while parsing (see idlnode.py), resolve any typedefs not resolved
# during parsing.  This must be done before the database is created, merged, and augmented to
# exact type matching.  Typedefs can be encountered in any IDL and usage can cross IDL boundaries.
def ResolveAllTypedefs(all_interfaces):
    # Resolve all typedefs.
    for interface, db_Opts in all_interfaces:

        def IsIdentified(idl_node):
            node_name = idl_node.id if idl_node.id else 'parent'
            for idl_type in idl_node.all(idlnode.IDLType):
                # One last check is the type a typedef in an IDL file (the typedefs
                # are treated as global).
                resolvedType = resolveTypedef(idl_type)
                if (resolvedType != idl_type):
                    idl_type.id = resolvedType.id
                    idl_type.nullable = resolvedType.nullable
                    continue
            return True

        interface.constants = list(filter(IsIdentified, interface.constants))
        interface.attributes = list(filter(IsIdentified, interface.attributes))
        interface.operations = list(filter(IsIdentified, interface.operations))
        interface.parents = list(filter(IsIdentified, interface.parents))


def build_database(idl_files,
                   database_dir,
                   feature_defines=None,
                   logging_level=logging.WARNING,
                   examine_idls=False):
    """This code reconstructs the FremontCut IDL database from W3C,
  WebKit and Dart IDL files."""
    current_dir = os.path.dirname(__file__)
    logging.config.fileConfig(os.path.join(current_dir, "logging.conf"))

    _logger.setLevel(logging_level)

    db = database.Database(database_dir)

    # Delete all existing IDLs in the DB.
    db.Delete()

    builder = databasebuilder.DatabaseBuilder(db)
    dependency.set_builder(builder)

    # TODO(vsm): Move this to a README.
    # This is the Chrome revision.
    webkit_revision = '63'

    # TODO(vsm): Reconcile what is exposed here and inside WebKit code
    # generation.  We need to recheck this periodically for now.
    webkit_defines = ['LANGUAGE_DART', 'LANGUAGE_JAVASCRIPT']

    if feature_defines is None:
        feature_defines = FEATURE_DEFINES

    webkit_options = databasebuilder.DatabaseBuilderOptions(
        # TODO(vsm): What else should we define as on when processing IDL?
        idl_defines=webkit_defines + feature_defines,
        source='WebKit',
        source_attributes={'revision': webkit_revision},
        logging_level=logging_level)

    # Import WebKit IDLs.
    builder.import_idl_files(idl_files, webkit_options, False)

    # Import Dart idl:
    dart_options = databasebuilder.DatabaseBuilderOptions(
        source='Dart',
        rename_operation_arguments_on_merge=True,
        logging_level=logging_level)

    utilities.KNOWN_COMPONENTS = frozenset(['core', 'modules', 'dart'])

    builder.import_idl_files(
        [os.path.join(current_dir, '..', 'idl', 'dart', 'dart.idl')],
        dart_options, True)

    start_time = time.time()

    # All typedefs MUST be resolved here before any database fixups (merging, implements, etc.)
    ResolveAllTypedefs(builder._imported_interfaces)

    # Merging:
    builder.merge_imported_interfaces()

    builder.fetch_constructor_data(webkit_options)
    builder.fix_displacements('WebKit')

    # Cleanup:
    builder.normalize_annotations(['WebKit', 'Dart'])

    # Map any IDL defined dictionaries to Dictionary.
    builder.map_dictionaries()

    # Examine all IDL and produce a diagnoses of areas (e.g., list dictionaries
    # declared and usage, etc.)
    if examine_idls:
        builder.examine_database()

    conditionals_met = set(
        'ENABLE_' + conditional for conditional in builder.conditionals_met)
    known_conditionals = set(FEATURE_DEFINES + FEATURE_DISABLED)

    unused_conditionals = known_conditionals - conditionals_met
    if unused_conditionals:
        _logger.warning('There are some unused conditionals %s' %
                        sorted(unused_conditionals))
        _logger.warning('Please update fremontcutbuilder.py')

    unknown_conditionals = conditionals_met - known_conditionals
    if unknown_conditionals:
        _logger.warning('There are some unknown conditionals %s' %
                        sorted(unknown_conditionals))
        _logger.warning('Please update fremontcutbuilder.py')

    print('Merging interfaces %s seconds' % round(time.time() - start_time, 2))

    return db


def main(parallel=False, logging_level=logging.WARNING, examine_idls=False):
    current_dir = os.path.dirname(__file__)

    idl_files = []

    # Check default location in a regular dart enlistment.
    webcore_dir = os.path.join(current_dir, '..', '..', '..', 'third_party',
                               'WebCore')

    if not os.path.exists(webcore_dir):
        # Check default location in a dartium enlistment.
        webcore_dir = os.path.join(current_dir, '..', '..', '..', '..',
                                   'third_party', 'WebKit', 'Source')

    if not os.path.exists(webcore_dir):
        raise RuntimeError('directory not found: %s' % webcore_dir)

    DIRS_TO_IGNORE = [
        'bindings',  # Various test IDLs
        'testing',  # IDLs to expose testing APIs
        'networkinfo',  # Not yet used in Blink yet
        'vibration',  # Not yet used in Blink yet
        'inspector',
        'idl_parser',  # idl_parser has test IDL files.
    ]

    # TODO(terry): Integrate this into the htmlrenamer's _removed_html_interfaces
    #              (if possible).
    FILES_TO_IGNORE = [
        'InspectorFrontendHostFileSystem.idl',  # Uses interfaces in inspector dir (which is ignored)
        'WebKitGamepad.idl',  # Gamepad.idl is the new one.
        'WebKitGamepadList.idl',  # GamepadList is the new one.
    ]

    for (dir_name, dirs, files) in os.walk(webcore_dir):
        if os.path.basename(dir_name) in DIRS_TO_IGNORE:
            dirs[:] = []  # Do not go underneath
        else:
            for name in files:
                file_name = os.path.join(dir_name, name)
                (interface, ext) = os.path.splitext(file_name)
                if ext == '.idl' and not (name in FILES_TO_IGNORE):
                    idl_files.append(file_name)

    database_dir = os.path.join(current_dir, '..', 'database')

    return build_database(
        idl_files,
        database_dir,
        logging_level=logging_level,
        examine_idls=examine_idls)


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