# Copyright 2018 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Recipe for generating docs."""

from recipe_engine.config import List
from recipe_engine.recipe_api import Property

TARGET_CPU = ['arm64', 'x64']

COMMIT_MESSAGE = """\
[gndoc] Update GN build arguments documentation

"""

DEPS = [
    'fuchsia/auto_roller',
    'fuchsia/checkout',
    'fuchsia/jiri',
    'recipe_engine/buildbucket',
    'recipe_engine/cipd',
    'recipe_engine/context',
    'recipe_engine/json',
    'recipe_engine/path',
    'recipe_engine/platform',
    'recipe_engine/properties',
    'recipe_engine/raw_io',
    'recipe_engine/step',
]

PROPERTIES = {
    'manifest':
        Property(kind=str, help='Jiri manifest to use'),
    'remote':
        Property(kind=str, help='Remote manifest repository'),
    'packages':
        Property(kind=List(basestring), help='Packages to build', default=[]),
    'run_gndoc':
        Property(kind=bool, help='Run gndoc', default=True),
    # Only run the Zircon portion of this if specified. This is because this
    # roller is run on the Fuchisa and the Topaz repos, and will likely be run
    # for other petal repos as they emerge.
    'do_zircon':
        Property(
            kind=bool, help='Also run for the Zircon GN build', default=False)
}


def gndoc(api, args, out_file):
  # Get the project list for linkifiying (need all projects).
  sources_path = api.path['cleanup'].join('projects.json')
  api.jiri.project(out=sources_path)

  # Output the docs in //docs/gen
  gen_doc_dir = api.path['start_dir'].join('docs', 'gen')

  # Gather args for running gndoc tool.
  gndoc_cmd = [
      api.path['start_dir'].join('cipd', 'gndoc'),
      '-key',
      'target_cpu',
      '-out',
      gen_doc_dir.join(out_file),
      '-s',
      sources_path,
  ] + args

  api.step('gndoc', gndoc_cmd)


def gn_gen(api, args, build_dir, outfile, target, platform):
  gn = api.path['start_dir'].join('prebuilt', 'third_party', 'gn', platform,
                                  'gn')
  # The build directory is root_build_dir, as this will end up in the
  # generated documenation for any arg that is declared in this directory.
  # $root_build_dir is a clear way to indicate from where the arg is named.
  gen_args = [
      gn,
      'gen',
      build_dir,
  ]
  if args:
    gen_args.append('--args=%s' % ' '.join(args))
  api.step('gn gen (%s)' % target, gen_args)

  api.step(
      'gn args --list (%s)' % target,
      [gn, 'args', build_dir, '--list', '--json'],
      stdout=api.raw_io.output(leak_to=outfile),
  )


def gn_zircon_args(api, platform):
  gn = api.path['start_dir'].join('prebuilt', 'third_party', 'gn', platform,
                                  'gn')
  zircon_path = api.path['start_dir'].join('zircon')
  zircon_data = api.path['cleanup'].join('zircon.json')

  api.step(
      'gn args --list (zircon)',
      [
          gn,
          '--root=%s' % zircon_path,
          'args',
          api.path['start_dir'].join('root_build_dir.zircon'),
          '--list',
          '--json',
      ],
      stdout=api.raw_io.output(leak_to=zircon_data),
  )

  gndoc(api, ['-in', zircon_data], 'zircon_build_arguments.md')


def gen_gndoc(api, packages, platform, do_zircon):
  gndoc_args = []
  # Generate a gn args json file for each build target.
  for target in TARGET_CPU:
    # Run gn and generate json file
    args = [
        'import("//boards/%s.gni")' % target,
        'import("//products/core.gni")',
    ]
    if packages:
      args.append('base_package_labels += ["%s"]' % '","'.join(packages))

    data = api.path['cleanup'].join('%s.json' % target)

    gn_gen(api, args, api.path['start_dir'].join('root_build_dir'), data,
           target, platform)
    if do_zircon and target == 'x64':
      gn_zircon_args(api, platform)
    # Add targets to gndoc command
    gndoc_args.extend(['-in', api.path['cleanup'].join('%s.json' % target)])

  gndoc(api, gndoc_args, 'build_arguments.md')


def RunSteps(api, manifest, remote, packages, run_gndoc, do_zircon):
  with api.step.nest('ensure_packages'):
    with api.context(infra_steps=True):
      pkgs = api.cipd.EnsureFile()
      pkgs.add_package('fuchsia/tools/gndoc/${platform}', 'latest')
      cipd_dir = api.path['start_dir'].join('cipd')
      api.cipd.ensure(cipd_dir, pkgs)

  checkout = api.checkout.fuchsia_with_options(
      path=api.path['start_dir'],
      build=api.buildbucket.build,
      manifest=manifest,
      remote=remote,
  )

  cpu = {
      'intel': {
          32: '386',
          64: 'x64',
      },
      'arm': {
          32: 'armv6',
          64: 'arm64',
      },
  }[api.platform.arch][api.platform.bits]
  platform = '%s-%s' % (api.platform.name.replace('win', 'windows'), cpu)

  if run_gndoc:
    with api.step.nest('gndoc'):
      gen_gndoc(api, packages, platform, do_zircon)

  api.auto_roller.attempt_roll(
      gerrit_project='fuchsia',
      repo_dir=checkout.root_dir,
      commit_message=COMMIT_MESSAGE)


def GenTests(api):
  roller_success = api.auto_roller.success_step_data()

  def properties(project):
    return api.properties(
        manifest='fuchsia',
        project='integration',
        remote='https://fuchsia.googlesource.com/fuchsia',
        packages=['//%s/packages:default' % project],
    )

  def gndoc_test_data(project):
    return api.step_data(
        'gndoc.jiri project',
        api.json.output([{
            'name': 'build',
            'path': '/path/to/build',
            'relativePath': 'build',
            'remote': 'https://fuchsia.googlesource.com/build',
        }])) + api.step_data(
            'gndoc.gn args --list (x64)',
            api.json.output([{
                'current': {
                    'file': '//' + project + '/out/x64/args.gn',
                    'line': 1,
                    'value': "\"x64\""
                },
                'default': {
                    'value': "\"\""
                },
                'name': 'target_cpu'
            }]))

  yield (api.test('fuchsia_docs') + api.buildbucket.ci_build(
      git_repo='https://fuchsia.googlesource.com/garnet') + roller_success +
         properties('fuchsia') + gndoc_test_data('fuchsia'))

  yield (api.test('zircon_docs') + api.buildbucket.ci_build(
      git_repo='https://fuchsia.googlesource.com/fuchsia') + roller_success +
         api.properties(
             manifest='fuchsia',
             project='integration',
             remote='https://fuchsia.googlesource.com/fuchsia',
             do_zircon=True,
         ) + gndoc_test_data('integration') + api.step_data(
             'gndoc.jiri project',
             api.json.output([{
                 'name': 'build',
                 'path': '/path/to/build',
                 'relativePath': 'build',
                 'remote': 'https://fuchsia.googlesource.com/build',
             }])) + api.step_data(
                 'gndoc.gn args --list (zircon)',
                 api.json.output([{
                     'current': {
                         'file': '//zircon/out/x64/args.gn',
                         'line': 1,
                         'value': "\"x64\""
                     },
                     'default': {
                         'value': "\"\""
                     },
                     'name': 'target_cpu'
                 }])))
