#!/usr/bin/env python3
# Copyright 2012 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Generator for C++ structs from api json files.

The purpose of this tool is to remove the need for hand-written code that
converts to and from base::Value types when receiving javascript api calls.
Originally written for generating code for extension apis. Reference schemas
are in chrome/common/extensions/api.

Usage example:
  compiler.py --root /home/Work/src --namespace extensions windows.json
    tabs.json
  compiler.py --destdir gen --root /home/Work/src
    --namespace extensions windows.json tabs.json
"""

import io
import optparse
import json_parse
import os
import shlex
import sys

from cpp_bundle_generator import CppBundleGenerator
from cpp_generator import CppGenerator
from cpp_namespace_environment import CppNamespaceEnvironment
from cpp_type_generator import CppTypeGenerator
from js_externs_generator import JsExternsGenerator
from js_interface_generator import JsInterfaceGenerator
import json_schema
from model import Model
from namespace_resolver import NamespaceResolver
from schema_loader import SchemaLoader
from ts_definition_generator import TsDefinitionGenerator

# Names of supported code generators, as specified on the command-line.
# First is default.
GENERATORS = [
    'cpp',
    'cpp-bundle-registration',
    'cpp-bundle-schema',
    'externs',
    'ts_definitions',
    'interface',
]


def DeleteNodes(item, delete_key=None, matcher=None):
  """Deletes certain nodes in item, recursively. If |delete_key| is set, all
  dicts with |delete_key| as an attribute are deleted. If a callback is passed
  as |matcher|, |DeleteNodes| will delete all dicts for which matcher(dict)
  returns True.
  """
  assert (delete_key is not None) != (matcher is not None)

  def ShouldDelete(thing):
    return json_parse.IsDict(thing) and (
        delete_key is not None and delete_key in thing
        or matcher is not None and matcher(thing))

  if json_parse.IsDict(item):
    toDelete = []
    for key, value in item.items():
      if ShouldDelete(value):
        toDelete.append(key)
      else:
        DeleteNodes(value, delete_key, matcher)
    for key in toDelete:
      del item[key]
  elif type(item) == list:
    item[:] = [
        DeleteNodes(thing, delete_key, matcher) for thing in item
        if not ShouldDelete(thing)
    ]

  return item


def GenerateSchema(
    generator_name,
    file_paths,
    root,
    destdir,
    cpp_namespace_pattern,
    bundle_name,
    impl_dir,
    include_rules,
):
  # Merge the source files into a single list of schemas.
  api_defs = []
  for file_path in file_paths:
    schema = os.path.relpath(file_path, root)
    api_def = SchemaLoader(root).LoadSchema(schema)

    # If compiling the C++ model code, delete 'nocompile' nodes.
    if generator_name == 'cpp':
      api_def = DeleteNodes(api_def, 'nocompile')

    api_defs.extend(api_def)

  api_model = Model()

  # For single-schema compilation make sure that the first (i.e. only) schema
  # is the default one.
  default_namespace = None

  # If we have files from multiple source paths, we'll use the common parent
  # path as the source directory.
  src_path = None

  # Load the actual namespaces into the model.
  for target_namespace, file_path in zip(api_defs, file_paths):
    relpath = os.path.relpath(os.path.normpath(file_path), root)
    namespace = api_model.AddNamespace(
        target_namespace,
        relpath,
        include_compiler_options=True,
        environment=CppNamespaceEnvironment(cpp_namespace_pattern),
    )

    if default_namespace is None:
      default_namespace = namespace

    if src_path is None:
      src_path = namespace.source_file_dir
    else:
      src_path = os.path.commonprefix((src_path, namespace.source_file_dir))

    _, filename = os.path.split(file_path)
    filename_base, _ = os.path.splitext(filename)

  # Construct the type generator with all the namespaces in this model.
  schema_dir = os.path.dirname(os.path.relpath(file_paths[0], root))
  namespace_resolver = NamespaceResolver(root, schema_dir, include_rules,
                                         cpp_namespace_pattern)
  type_generator = CppTypeGenerator(api_model, namespace_resolver,
                                    default_namespace)
  if generator_name in ('cpp-bundle-registration', 'cpp-bundle-schema'):
    cpp_bundle_generator = CppBundleGenerator(
        root,
        api_model,
        api_defs,
        type_generator,
        cpp_namespace_pattern,
        bundle_name,
        src_path,
        impl_dir,
    )
    if generator_name == 'cpp-bundle-registration':
      generators = [
          (
              'generated_api_registration.cc',
              cpp_bundle_generator.api_cc_generator,
          ),
          (
              'generated_api_registration.h',
              cpp_bundle_generator.api_h_generator,
          ),
      ]
    elif generator_name == 'cpp-bundle-schema':
      generators = [
          ('generated_schemas.cc', cpp_bundle_generator.schemas_cc_generator),
          ('generated_schemas.h', cpp_bundle_generator.schemas_h_generator),
      ]
  elif generator_name == 'cpp':
    cpp_generator = CppGenerator(type_generator)
    generators = [
        ('%s.h' % filename_base, cpp_generator.h_generator),
        ('%s.cc' % filename_base, cpp_generator.cc_generator),
    ]
  elif generator_name == 'externs':
    generators = [('%s_externs.js' % namespace.unix_name, JsExternsGenerator())]
  elif generator_name == 'ts_definitions':
    generators = [('%s.d.ts' % namespace.unix_name, TsDefinitionGenerator())]
  elif generator_name == 'interface':
    generators = [(
        '%s_interface.js' % namespace.unix_name,
        JsInterfaceGenerator(),
    )]
  else:
    raise Exception('Unrecognised generator %s' % generator_name)

  output_code = []
  for filename, generator in generators:
    code = generator.Generate(namespace).Render()
    if destdir:
      if generator_name == 'cpp-bundle-registration':
        # Function registrations must be output to impl_dir, since they link in
        # API implementations.
        output_dir = os.path.join(destdir, impl_dir)
      else:
        output_dir = os.path.join(destdir, src_path)
      if not os.path.exists(output_dir):
        os.makedirs(output_dir)
      generator_filepath = os.path.join(output_dir, filename)
      with io.open(generator_filepath, 'w', encoding='utf-8') as f:
        f.write(code)
    # If multiple files are being output, add the filename for each file.
    if len(generators) > 1:
      output_code += [filename, '', code, '']
    else:
      output_code += [code]

  return '\n'.join(output_code)


if __name__ == '__main__':
  parser = optparse.OptionParser(
      description='Generates a C++ model of an API from JSON schema',
      usage='usage: %prog [option]... schema',
  )
  parser.add_option(
      '-r',
      '--root',
      default='.',
      help=(
          'logical include root directory. Path to schema files from specified'
          ' dir will be the include path.'),
  )
  parser.add_option('-d',
                    '--destdir',
                    help='root directory to output generated files.')
  parser.add_option(
      '-n',
      '--namespace',
      default='generated_api_schemas',
      help='C++ namespace for generated files. e.g extensions::api.',
  )
  parser.add_option(
      '-b',
      '--bundle-name',
      default='',
      help=('A string to prepend to generated bundle class names, so that '
            'multiple bundle rules can be used without conflicting. '
            'Only used with one of the cpp-bundle generators.'),
  )
  parser.add_option(
      '-g',
      '--generator',
      default=GENERATORS[0],
      choices=GENERATORS,
      help=(
          'The generator to use to build the output code. Supported values are'
          ' %s') % GENERATORS,
  )
  parser.add_option(
      '-i',
      '--impl-dir',
      dest='impl_dir',
      help='The root path of all API implementations',
  )
  parser.add_option(
      '-I',
      '--include-rules',
      help=('A list of paths to include when searching for referenced objects,'
            " with the namespace separated by a ':'. Example: "
            '/foo/bar:Foo::Bar::%(namespace)s'),
  )

  (opts, file_paths) = parser.parse_args()

  if not file_paths:
    sys.exit(0)  # This is OK as a no-op

  # Unless in bundle mode, only one file should be specified.
  if (opts.generator not in ('cpp-bundle-registration', 'cpp-bundle-schema')
      and len(file_paths) > 1):
    # TODO(sashab): Could also just use file_paths[0] here and not complain.
    raise Exception(
        'Unless in bundle mode, only one file can be specified at a time.')

  def split_path_and_namespace(path_and_namespace):
    if ':' not in path_and_namespace:
      raise ValueError(
          'Invalid include rule "%s". Rules must be of the form path:namespace'
          % path_and_namespace)
    return path_and_namespace.split(':', 1)

  include_rules = []
  if opts.include_rules:
    include_rules = list(
        map(split_path_and_namespace, shlex.split(opts.include_rules)))

  result = GenerateSchema(
      opts.generator,
      file_paths,
      opts.root,
      opts.destdir,
      opts.namespace,
      opts.bundle_name,
      opts.impl_dir,
      include_rules,
  )
  if not opts.destdir:
    print(result)
