#!/usr/bin/python

#
# Copyright 2016 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 IDL files for interfaces that are not implemented in Cobalt.

This will do a shallow clone of the chromium repository and gather the set of
all IDL files. These IDLs will be flattened so that there is one IDL per
interface. That is, no IDLs will have partial interfaces nor will any IDL use
the "implements" keyword.
These IDL files are diff'd against the same flattened IDL files from Cobalt, and
new IDL files representing the unimplemented interfaces and properties will be
written to the output directory.
"""

import argparse
import logging
import os
import shutil
import subprocess
import sys
import tempfile
import textwrap

from flatten_idls import FlattenedInterface

_SCRIPT_DIR = os.path.dirname(__file__)
_CHROMIUM_REPOSITORY_URL = 'https://chromium.googlesource.com/chromium/src'
_UNIMPLEMENTED_INTERFACE_TEMPLATE = '[NotSupported] interface {} {{}};\n'


def _ClobberDirectory(dirname):
  """Delete the directory if it exists, and create it if it does not."""
  if os.path.exists(dirname):
    shutil.rmtree(dirname)
  os.makedirs(dirname)


def _CloneChromium(branch, destination_dir):
  """Clone the specified branch of Chromium to the specified directory.

  Only do a shallow clone since we don't care about the full history.

  Args:
    branch: Name of a branch in Chromium's git repository.
    destination_dir: Directory into which Chromium repository will be cloned.
  """
  clone_command = ['git', 'clone', '--depth', '1', '--branch', branch,
                   _CHROMIUM_REPOSITORY_URL, '.']
  subprocess.check_call(clone_command, cwd=destination_dir)


def _LoadInterfaces(interfaces_pickle):
  """Load the interfaces from a pickle and return a name->interface dict."""
  interfaces = FlattenedInterface.LoadFromPickle(interfaces_pickle)
  return dict(((interface.name, interface) for interface in interfaces))


def _WriteUnsupportedInterfaceIDL(interface_name, output_dir):
  """Write out InterfaceName.idl for an unsupported interface.

  The interface will have the [NotSupported] attribute set.

  Args:
    interface_name: The name of the interface whose IDL file will be created.
    output_dir: Directory into which the generated IDL file will be written.
  """
  output_idl_filename = os.path.join(output_dir, interface_name) + '.idl'
  with open(output_idl_filename, 'w') as f:
    f.write(_UNIMPLEMENTED_INTERFACE_TEMPLATE.format(interface_name))


def _WritePartiallySupportedInterfaceIDL(interface, output_dir):
  """Write out InterfaceName_unsupported.idl.

  Unsupported interface members will have the [NotSupported] extended attribute.

  Args:
    interface: A FlattenedInterface object.
    output_dir: Directory into which the generated IDL file will be written.
  """
  output_idl_filename = os.path.join(output_dir,
                                     interface.name) + '_unsupported.idl'
  with open(output_idl_filename, 'w') as f:
    f.write('partial interface %s {\n' % interface.name)
    for c in interface.constants:
      # Type doesn't matter so use long
      f.write('  [NotSupported] const long %s;\n' % c)
    for a in interface.attributes:
      f.write('  [NotSupported] attribute long %s;\n' % a)
    for o in interface.operations:
      f.write('  [NotSupported] void %s();\n' % o)
    f.write('}\n')


def main(argv):
  """Main function."""
  parser = argparse.ArgumentParser(
      formatter_class=argparse.RawDescriptionHelpFormatter,
      description=textwrap.dedent(__doc__))
  parser.add_argument(
      '--branch',
      help='Branch or tag to fetch from the chromium repository. '
      'This will be passed to git clone\'s -b parameter.')
  parser.add_argument(
      '--chromium_dir',
      help='Directory containing a chromium repository. If the --branch '
      'argument is set, the directory will be clobbered and the specified '
      'branch will be cloned into this directory.')
  parser.add_argument('--output_dir',
                      required=True,
                      help='Directory into which IDL files will be placed. '
                      'The current contents will be clobbered.')

  options = parser.parse_args(argv)
  logging_format = '%(asctime)s %(levelname)-8s %(message)s'
  logging.basicConfig(level=logging.INFO,
                      format=logging_format,
                      datefmt='%m-%d %H:%M')

  temp_dir = tempfile.mkdtemp()

  try:
    if not options.chromium_dir:
      chromium_dir = os.path.join(temp_dir, 'chromium')
      os.makedirs(chromium_dir)
    else:
      chromium_dir = options.chromium_dir

    if options.branch:
      logging.info('Cloning chromium branch %s into %s', options.branch,
                   chromium_dir)
      _ClobberDirectory(chromium_dir)
      # Git clone into temp_dir
      _CloneChromium(options.branch, chromium_dir)
    else:
      assert os.path.isdir(chromium_dir)

    # Gather the blink IDLs
    logging.info('Gathering blink IDLs.')
    blink_pickle_file = os.path.join(temp_dir, 'blink_idl.pickle')
    subprocess.check_call(
        ['python', 'flatten_idls.py', '--directory', os.path.join(
            chromium_dir, 'third_party/WebKit/Source/core'), '--directory',
         os.path.join(chromium_dir, 'third_party/WebKit/Source/modules'),
         '--ignore', '*/InspectorInstrumentation.idl', '--blink_scripts_dir',
         os.path.join(chromium_dir,
                      'third_party/WebKit/Source/bindings/scripts'),
         '--output_path', blink_pickle_file])

    # Gather Cobalt's IDLs
    logging.info('Gathering Cobalt IDLs.')
    cobalt_root = os.path.join(_SCRIPT_DIR, '../../../')
    cobalt_pickle_file = os.path.join(temp_dir, 'cobalt_idl.pickle')
    subprocess.check_call(
        ['python', 'flatten_idls.py', '--directory', os.path.join(
            cobalt_root, 'cobalt'), '--ignore', '*/cobalt/bindings/*',
         '--blink_scripts_dir', os.path.join(
             cobalt_root, 'third_party/blink/Source/bindings/scripts'),
         '--output_path', cobalt_pickle_file])

    # Unpickle the files.
    blink_interfaces = _LoadInterfaces(blink_pickle_file)
    cobalt_interfaces = _LoadInterfaces(cobalt_pickle_file)

    blink_interface_names = set(blink_interfaces.keys())
    cobalt_interface_names = set(cobalt_interfaces.keys())

    _ClobberDirectory(options.output_dir)

    # Write out an IDL for unimplemented interfaces. For simplicity, an IDL will
    # be written out for each named constructor as well.
    for interface_name in blink_interface_names.difference(
        cobalt_interface_names):
      interface = blink_interfaces[interface_name]
      for constructor in interface.constructors:
        _WriteUnsupportedInterfaceIDL(constructor, options.output_dir)

    # Get all the cobalt interfaces that are also in blink
    for interface_name in cobalt_interface_names.intersection(
        blink_interface_names):
      unimplemented = FlattenedInterface.Difference(
          blink_interfaces[interface_name], cobalt_interfaces[interface_name])
      if not unimplemented.IsEmpty():
        _WritePartiallySupportedInterfaceIDL(unimplemented, options.output_dir)
  finally:
    shutil.rmtree(temp_dir)

  return 0


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