# 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

from PB.recipes.flutter.engine.engine_lint import InputProperties
from PB.recipes.flutter.engine.engine_lint import EnvProperties

DEPS = [
    'depot_tools/depot_tools',
    'depot_tools/gclient',
    'flutter/build_util',
    'flutter/flutter_deps',
    'flutter/logs_util',
    'flutter/os_utils',
    'flutter/osx_sdk',
    'flutter/repo_util',
    'flutter/retry',
    'flutter/test_utils',
    'recipe_engine/buildbucket',
    'recipe_engine/context',
    'recipe_engine/file',
    'recipe_engine/path',
    'recipe_engine/platform',
    'recipe_engine/properties',
    'recipe_engine/runtime',
    'recipe_engine/step',
]

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

PROPERTIES = InputProperties
ENV_PROPERTIES = EnvProperties


def GetCheckoutPath(api):
  return api.path['cache'].join('builder', 'src')


def RunGN(api, *args):
  checkout = GetCheckoutPath(api)
  api.build_util.run_gn(args, checkout)


def Build(api, config, *targets):
  checkout = GetCheckoutPath(api)
  api.build_util.build(config, checkout, targets)


def Lint(api, config, shardId=None, shardVariants=""):
  checkout = GetCheckoutPath(api)
  with api.context(cwd=checkout):
    lint_cmd = checkout.join('flutter', 'ci', 'lint.sh')
    cmd = [lint_cmd, '--variant', config]
    if api.properties.get('lint_all', True):
      cmd += ['--lint-all']
    if api.properties.get('lint_head', False):
      cmd += ['--lint-head']
    if shardId != None:
      cmd += ['--shard-id=%d' % shardId, '--shard-variants=%s' % shardVariants]
    api.step(api.test_utils.test_step_name('lint %s' % config), cmd)


def DoLints(api):
  if api.platform.is_linux:
    RunGN(api, '--android', '--android-cpu', 'arm64', '--no-lto')
    RunGN(api, '--runtime-mode', 'debug', '--prebuilt-dart-sdk', '--no-lto')
    if api.properties.get('lint_android', True):
      Build(api, 'android_debug_arm64')
      Lint(api, 'android_debug_arm64', shardId=0, shardVariants="host_debug")

    if api.properties.get('lint_host', True):
      # We have to build before linting because source files #include header
      # files that are generated during the build.
      Build(api, 'host_debug')
      Lint(api, 'host_debug', shardId=1, shardVariants="android_debug_arm64")

  elif api.platform.is_mac:
    with api.osx_sdk('ios'):
      RunGN(
          api, '--ios', '--runtime-mode', 'debug', '--simulator', '--no-lto',
      )
      RunGN(api, '--runtime-mode', 'debug', '--prebuilt-dart-sdk', '--no-lto')
      if api.properties.get('lint_ios', True):
        Build(api, 'ios_debug_sim')
        Lint(api, 'ios_debug_sim', shardId=0, shardVariants="host_debug")

      if api.properties.get('lint_host', True):
        # We have to build before linting because source files #include header
        # files that are generated during the build.
        Build(api, 'host_debug')
        Lint(api, 'host_debug', shardId=1, shardVariants="ios_debug_sim")


def RunSteps(api, properties, env_properties):
  # Collect memory/cpu/process before task execution.
  api.os_utils.collect_os_info()

  cache_root = api.path['cache'].join('builder')
  checkout = GetCheckoutPath(api)

  api.file.ensure_directory('Ensure checkout cache', cache_root)
  dart_bin = checkout.join(
      'third_party', 'dart', 'tools', 'sdks', 'dart-sdk', 'bin'
  )

  android_home = checkout.join('third_party', 'android_tools', 'sdk')

  env = {
    'ANDROID_HOME': str(android_home),
    'FLUTTER_PREBUILT_DART_SDK': 'True',
  }
  env_prefixes = {'PATH': [dart_bin]}

  api.logs_util.initialize_logs_collection(env)

  # Add certificates and print the ones required for pub.
  api.flutter_deps.certs(env, env_prefixes)
  api.os_utils.print_pub_certs()

  # Enable long path support on Windows.
  api.os_utils.enable_long_paths()

  api.repo_util.engine_checkout(cache_root, env, env_prefixes)

  # Delete derived data on mac. This is a noop for other platforms.
  api.os_utils.clean_derived_data()

  # Various scripts we run assume access to depot_tools on path for `ninja`.
  with api.context(cwd=cache_root, env=env,
                   env_prefixes=env_prefixes), api.depot_tools.on_path():

    api.gclient.runhooks()

    try:
      DoLints(api)
    finally:
      api.logs_util.upload_logs('engine')
      # 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()


# pylint: disable=line-too-long
# See https://chromium.googlesource.com/infra/luci/recipes-py/+/refs/heads/master/doc/user_guide.md
# The tests in here make sure that every line of code is used and does not fail.
# pylint: enable=line-too-long
def GenTests(api):
  for platform in ('mac', 'linux'):
    for lint_set in ('all', 'head', 'branch'):
      for lint_target in ('host', 'ios', 'android'):
        if lint_target == 'ios' and platform == 'linux':
          continue
        if lint_target == 'android' and platform == 'mac':
          continue
        test = api.test(
            '%s %s %s' % (
                platform, lint_target, lint_set,
            ),
            api.platform(platform, 64),
            api.buildbucket.ci_build(
                builder='%s Engine Lint' % platform.capitalize(),
                git_repo=GIT_REPO,
                project='flutter',
            ),
            api.runtime(is_experimental=False),
            api.properties(
                InputProperties(
                    goma_jobs='1024',
                    lint_all=lint_set == 'all',
                    lint_head=lint_set == 'head',
                    lint_host=lint_target == 'host',
                    lint_android=lint_target == 'android',
                    lint_ios=lint_target == 'ios',
                ),
            ),
            api.properties.environ(
                EnvProperties(SWARMING_TASK_ID='deadbeef')
            ),
        )
        yield test
