#!/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.
"""This is the entry point to create Dart APIs from the IDL database."""

import css_code_generator
import os
import sys

# Setup all paths to find our PYTHON code

# dart_dir is the location of dart's enlistment dartium (dartium-git/src/dart)
# and Dart (dart-git/dart).
dart_dir = os.path.abspath(
    os.path.normpath(os.path.join(os.path.dirname(__file__), '..', '..', '..')))
sys.path.insert(1, os.path.join(dart_dir, 'tools/dom/new_scripts'))
sys.path.insert(1, os.path.join(dart_dir,
                                'third_party/WebCore/bindings/scripts'))

# Dartium's third_party directory location is dartium-git/src/third_party
# and Dart's third_party directory location is dart-git/dart/third_party.
third_party_dir = os.path.join(dart_dir, 'third_party')

ply_dir = os.path.join(third_party_dir, 'ply')
# If ply directory found then we're a Dart enlistment; third_party location
# is dart-git/dart/third_party
if not os.path.exists(ply_dir):
    # For Dartium (ply directory is dartium-git/src/third_party/ply) third_party
    # location is dartium-git/src/third_party
    third_party_dir = os.path.join(dart_dir, '..', 'third_party')
    assert (os.path.exists(third_party_dir))
else:
    # It's Dart we need to make sure that WebCore is injected in our search path
    # because this is where idl_parser is located for a Dart enlistment. Dartium
    # can figure out the tools directory because of the location of where the
    # scripts blink scripts are located.
    sys.path.insert(1, os.path.join(dart_dir, 'third_party/WebCore'))

sys.path.insert(1, third_party_dir)

sys.path.insert(1, os.path.join(dart_dir, 'tools/dom/scripts'))

import dartgenerator
import database
import fremontcutbuilder
import logging
import monitored
import multiemitter
import optparse
import shutil
import subprocess
import time
from dartmetadata import DartMetadata
from generator import TypeRegistry
from generate_blink_file import Generate_Blink
from htmleventgenerator import HtmlEventGenerator
from htmlrenamer import HtmlRenamer
from prototype_htmleventgenerator import Prototype_HtmlEventGenerator
from systemhtml import DartLibraryEmitter, Dart2JSBackend,\
                       HtmlDartInterfaceGenerator, DartLibrary, DartLibraries,\
                       HTML_LIBRARY_NAMES
from systemnative import CPPLibraryEmitter, DartiumBackend
from templateloader import TemplateLoader

sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..'))

import utils

_logger = logging.getLogger('dartdomgenerator')


class GeneratorOptions(object):

    def __init__(self, templates, database, type_registry, renamer, metadata,
                 dart_js_interop):
        self.templates = templates
        self.database = database
        self.type_registry = type_registry
        self.renamer = renamer
        self.metadata = metadata
        self.dart_js_interop = dart_js_interop


def LoadDatabase(database_dir, use_database_cache):
    common_database = database.Database(database_dir)
    if use_database_cache:
        common_database.LoadFromCache()
    else:
        common_database.Load()
    return common_database


def GenerateFromDatabase(common_database,
                         dart2js_output_dir,
                         update_dom_metadata=False,
                         logging_level=logging.WARNING,
                         dart_js_interop=False,
                         generate_static_extensions=False,
                         generate_prototype_events=False):
    print('\n ----- Accessing DOM using %s -----\n' %
          ('dart:js' if dart_js_interop else 'C++'))

    start_time = time.time()

    current_dir = os.path.dirname(__file__)
    auxiliary_dir = os.path.join(current_dir, '..', 'src')
    template_dir = os.path.join(current_dir, '..', 'templates')

    _logger.setLevel(logging_level)

    generator = dartgenerator.DartGenerator(logging_level)
    generator.LoadAuxiliary(auxiliary_dir)

    generator.FilterMembersWithUnidentifiedTypes(common_database)
    webkit_database = common_database.Clone()

    # Generate Dart interfaces for the WebKit DOM.
    generator.FilterInterfaces(
        database=webkit_database,
        or_annotations=['WebKit', 'Dart'],
        exclude_displaced=['WebKit'],
        exclude_suppressed=['WebKit', 'Dart'])
    generator.FixEventTargets(webkit_database)
    generator.AddMissingArguments(webkit_database)
    generator.CleanupOperationArguments(webkit_database)

    emitters = multiemitter.MultiEmitter(logging_level)
    metadata = DartMetadata(os.path.join(current_dir, '..', 'dom.json'),
                            os.path.join(current_dir, '..', 'docs.json'),
                            logging_level)
    renamer = HtmlRenamer(webkit_database, metadata)
    type_registry = TypeRegistry(webkit_database, renamer)

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

    def RunGenerator(dart_libraries, dart_output_dir, template_loader,
                     backend_factory, dart_js_interop):
        options = GeneratorOptions(template_loader, webkit_database,
                                   type_registry, renamer, metadata,
                                   dart_js_interop)
        dart_library_emitter = DartLibraryEmitter(emitters, dart_output_dir,
                                                  dart_libraries)
        event_generator = HtmlEventGenerator(webkit_database, renamer, metadata,
                                             template_loader)
        prototype_event_generator = Prototype_HtmlEventGenerator(
            webkit_database, renamer, metadata, event_generator)

        def generate_interface(interface, gl_constants=None):
            backend = backend_factory(interface)
            interface_generator = HtmlDartInterfaceGenerator(
                options, dart_library_emitter, event_generator,
                prototype_event_generator, interface, backend)
            interface_generator.Generate()
            if len(backend._gl_constants) > 0 and not (gl_constants is None):
                gl_constants.extend(backend._gl_constants)

        generator.Generate(webkit_database, common_database, generate_interface)
        if generate_prototype_events:
            dart_bin = os.path.join(utils.CheckedInSdkPath(), 'bin', 'dart')
            prototype_event_generator.WriteFile(dart_bin)

        dart_library_emitter.EmitLibraries(auxiliary_dir, dart_js_interop)

    if dart2js_output_dir:
        template_paths = ['html/dart2js', 'html/impl', 'html/interface', '']
        template_loader = TemplateLoader(template_dir, template_paths, {
            'DARTIUM': False,
            'DART2JS': True,
            'JSINTEROP': False,
            'NNBD': True,
        })
        backend_options = GeneratorOptions(template_loader, webkit_database,
                                           type_registry, renamer, metadata,
                                           dart_js_interop)

        backend_factory = lambda interface:\
            Dart2JSBackend(interface, backend_options, logging_level, generate_static_extensions)

        dart_output_dir = os.path.join(dart2js_output_dir, 'dart')
        dart_libraries = DartLibraries(HTML_LIBRARY_NAMES, template_loader,
                                       'dart2js', dart2js_output_dir,
                                       dart_js_interop)
        for file in generator._auxiliary_files.values():
            if file.endswith('darttemplate'):
                dart_libraries._libraries['html'].AddFile(file)

        print('\nGenerating dart2js:\n')
        start_time = time.time()

        RunGenerator(dart_libraries, dart_output_dir, template_loader,
                     backend_factory, dart_js_interop)

        print('Generated dart2js in %s seconds' %
              round(time.time() - start_time, 2))

    emitters.Flush()

    if update_dom_metadata:
        metadata.Flush()

    monitored.FinishMonitoring(dart2js_output_dir, _logger)


def GenerateSingleFile(library_path, output_dir, generated_output_dir=None, prefix=None):
    library_dir = os.path.dirname(library_path)
    library_filename = os.path.basename(library_path)
    copy_dart_script = os.path.relpath('../../copy_dart.py', library_dir)
    output_dir = os.path.relpath(output_dir, library_dir)
    if not os.path.exists(library_dir):
        os.makedirs(library_dir)
    prefix_arg = 'export DART_HTML_PREFIX="' + prefix + '";' if prefix else ""
    command = ' '.join([
        prefix_arg, 'cd', library_dir, ';', copy_dart_script, output_dir, library_filename
    ])
    subprocess.call([command], shell=True)
    dart_bin = os.path.join(utils.CheckedInSdkPath(), 'bin', 'dart')
    sdk_file = os.path.join(library_dir, output_dir, library_filename)
    formatCommand = ' '.join([dart_bin, 'format', sdk_file])
    subprocess.call([formatCommand], shell=True)


def UpdateCssProperties():
    """Regenerate the CssStyleDeclaration template file with the current CSS
  properties."""
    _logger.info('Updating Css Properties.')
    css_code_generator.GenerateCssTemplateFile()


CACHED_PATCHES = """
// START_OF_CACHED_PATCHES
// Copyright (c) 2013, 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.

// DO NOT EDIT GENERATED FILE.

library cached_patches;

var cached_patches = {
    /********************************************************
     *****                                              *****
     *****  MUST RUN tools/dartium/generate_patches.sh  *****
     *****                                              *****
     ********************************************************/
};
"""


def main():
    parser = optparse.OptionParser()
    parser.add_option(
        '--parallel',
        dest='parallel',
        action='store_true',
        default=False,
        help='Use fremontcut in parallel mode.')
    parser.add_option(
        '--systems',
        dest='systems',
        action='store',
        type='string',
        default='htmldart2js,htmldartium,_blink',
        help='Systems to generate (htmldart2js, htmldartium, _blink)')
    parser.add_option(
        '--output-dir',
        dest='output_dir',
        action='store',
        type='string',
        default=None,
        help='Directory to put the generated files')
    parser.add_option(
        '--use-database-cache',
        dest='use_database_cache',
        action='store_true',
        default=False,
        help='''Use the cached database from the previous run to
                    improve startup performance''')
    parser.add_option(
        '--update-dom-metadata',
        dest='update_dom_metadata',
        action='store_true',
        default=False,
        help='''Update the metadata list of DOM APIs''')
    parser.add_option(
        '--verbose',
        dest='logging_level',
        action='store_false',
        default=logging.WARNING,
        help='Output all informational messages')
    parser.add_option(
        '--examine',
        dest='examine_idls',
        action='store_true',
        default=None,
        help='Analyze IDL files')
    parser.add_option(
        '--logging',
        dest='logging',
        type='int',
        action='store',
        default=logging.NOTSET,
        help='Level of logging 20 is Info, 30 is Warnings, 40 is Errors')
    parser.add_option(
        '--gen-interop',
        dest='dart_js_interop',
        action='store_true',
        default=False,
        help='Use JavaScript objects (dart:js) accessing the DOM in _blink')
    parser.add_option(
        '--no-cached-patches',
        dest='no_cached_patches',
        action='store_true',
        default=False,
        help='Do not generate the sdk/lib/js/cached_patches.dart file')
    parser.add_option(
        '--generate-static-extensions',
        dest='generate_static_extensions',
        action='store_true',
        default=False,
        help='Generate static extension members for dart:html classes')
    parser.add_option(
        '--generate-prototype-events',
        dest='generate_prototype_events',
        action='store_true',
        default=False,
        help='Generate event stream library for dart:html prototype')

    (options, args) = parser.parse_args()

    current_dir = os.path.dirname(__file__)
    database_dir = os.path.join(current_dir, '..', 'database')
    logging.config.fileConfig(os.path.join(current_dir, 'logging.conf'))
    systems = options.systems.split(',')

    output_dir = options.output_dir or os.path.join(
        current_dir, '..', '..', '..', utils.GetBuildDir(utils.GuessOS()),
        'generated')

    dart2js_output_dir = None
    if 'htmldart2js' in systems:
        dart2js_output_dir = os.path.join(output_dir, 'dart2js')

    logging_level = options.logging_level \
      if options.logging == logging.NOTSET else options.logging

    start_time = time.time()

    UpdateCssProperties()

    # Parse the IDL and create the database.
    database = fremontcutbuilder.main(
        options.parallel,
        logging_level=logging_level,
        examine_idls=options.examine_idls)

    GenerateFromDatabase(database, dart2js_output_dir,
                         options.update_dom_metadata, logging_level,
                         options.dart_js_interop,
                         options.generate_static_extensions,
                         options.generate_prototype_events)

    file_generation_start_time = time.time()

    if 'htmldart2js' in systems:
        _logger.info('Generating dart2js single files.')

        for library_name in HTML_LIBRARY_NAMES:
            source = os.path.join(dart2js_output_dir,
                                  '%s_dart2js.dart' % library_name)
            GenerateSingleFile(
                source, os.path.join('..', '..', '..', 'sdk', 'lib',
                                     library_name, 'dart2js'))

    print('\nGenerating single file %s seconds' %
          round(time.time() - file_generation_start_time, 2))

    end_time = time.time()

    print('\nDone (dartdomgenerator) %s seconds' %
          round(end_time - start_time, 2))


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