# Copyright 2016 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

from contextlib import contextmanager
import contextlib

from PB.recipes.flutter.engine.engine_builder import InputProperties, EngineBuild

DEPS = [
  'depot_tools/depot_tools',
  'flutter/goma',
  'flutter/os_utils',
  'flutter/osx_sdk',
  'flutter/repo_util',
  'flutter/shard_util_v2',
  'recipe_engine/buildbucket',
  'recipe_engine/cas',
  'recipe_engine/context',
  'recipe_engine/file',
  'recipe_engine/path',
  'recipe_engine/platform',
  'recipe_engine/properties',
  'recipe_engine/step',
]

GIT_REPO = \
    'https://flutter.googlesource.com/mirrors/engine'

PROPERTIES = InputProperties


def Build(api, config, disable_goma, *targets):
  checkout = api.path['cache'].join('builder', 'src')
  build_dir = checkout.join('out/%s' % config)
  ninja_path = checkout.join('flutter', 'third_party', 'ninja', 'ninja')

  if not disable_goma:
    ninja_args = [ninja_path, '-C', build_dir]
    ninja_args.extend(targets)
    with api.goma():
      name='build %s' % ' '.join([config] + list(targets))
      api.step(name, ninja_args)
  else:
    ninja_args = [ninja_path, '-C', build_dir]
    ninja_args.extend(targets)
    api.step('build %s' % ' '.join([config] + list(targets)), ninja_args)


def RunGN(api, disable_goma, *args):
  checkout = api.path['cache'].join('builder', 'src')
  gn_cmd = ['python3', checkout.join('flutter/tools/gn')]
  gn_cmd.extend(args)
  if disable_goma:
    api.step('gn %s' % ' '.join(args), gn_cmd)
  else:
    # Run gn within a context.
    env = {'GOMA_DIR': api.goma.goma_dir.get_result()}
    with api.context(env=env):
      api.step('gn %s' % ' '.join(args), gn_cmd)



def CasOutputs(api, output_files, output_dirs):
  out_dir = api.path['cache'].join('builder', 'src')
  dirs = output_files + output_dirs
  dirs = [api.path.abspath(d) for d in dirs]
  return api.cas.archive('CAS build outputs', out_dir, *dirs)


def RunSteps(api, properties):
  # Collect memory/cpu/process after task execution.
  api.os_utils.collect_os_info()
  cache_root = api.path['cache'].join('builder')
  api.file.rmtree('Clobber build output', cache_root.join('src', 'out'))
  api.repo_util.engine_checkout(cache_root, {}, {})
  with api.context(cwd=cache_root):
    android_home = cache_root.join('src', 'third_party', 'android_tools', 'sdk')
    env = {'ANDROID_HOME': str(android_home)}

    output_files = []
    output_dirs = []
    with api.osx_sdk('ios'), api.depot_tools.on_path(), api.context(
        env=env), api.step.defer_results():
      for build in properties.builds:
        with api.step.nest('build %s (%s)' %
                           (build.dir, ','.join(build.targets))):
          RunGN(api, build.disable_goma, *build.gn_args)
          Build(api, build.dir, build.disable_goma, *build.targets)
          for output_file in build.output_files:
            output_files.append(
                cache_root.join('src', 'out', build.dir, output_file))
          for output_dir in build.output_dirs:
            output_dirs.append(
                cache_root.join('src', 'out', build.dir, output_dir))
      # This is to clean up leaked processes.
      api.os_utils.kill_processes()
      # Collect memory/cpu/process after task execution.
      api.os_utils.collect_os_info()

    cas_hash = CasOutputs(api, output_files, output_dirs)
    output_props = api.step('Set output properties', None)
    output_props.presentation.properties['cas_output_hash'] = cas_hash


def GenTests(api):
  yield api.test(
      'Schedule two builds one with goma and one without',
      api.platform('linux', 64),
      api.buildbucket.ci_build(
          builder='Linux Drone',
          git_repo=GIT_REPO,
          project='flutter',
      ),
      api.properties(
          InputProperties(
              mastername='client.flutter',
              builds=[
                  EngineBuild(
                      disable_goma=True,
                      gn_args=['--unoptimized', '--android'],
                      dir='android_debug_unopt',
                      output_files=['libflutter.so'],
                      output_dirs=['some_dir'],
                  ),
                  EngineBuild(
                      disable_goma=False,
                      gn_args=['--unoptimized'],
                      dir='host_debug_unopt',
                      output_files=['shell_unittests'])
              ]
          )
      )
  )
