# 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 re

PYTHON_VERSION_COMPATIBILITY = 'PY3'

DEPS = [
    'depot_tools/depot_tools',
    'depot_tools/git',
    'flutter/flutter_deps',
    'flutter/repo_util',
    'recipe_engine/buildbucket',
    'recipe_engine/cipd',
    'recipe_engine/context',
    'recipe_engine/file',
    'recipe_engine/path',
    'recipe_engine/platform',
    'recipe_engine/properties',
    'recipe_engine/runtime',
    'recipe_engine/step',
]

PACKAGED_REF_RE = re.compile(r'^refs/heads/(dev|beta|stable)$')


@contextmanager
def Install7za(api):
  if api.platform.is_win:
    sevenzip_cache_dir = api.path['cache'].join('builder', '7za')
    api.cipd.ensure(
        sevenzip_cache_dir,
        api.cipd.EnsureFile().add_package(
            'flutter_internal/tools/7za/${platform}', 'version:19.00'
        )
    )
    with api.context(env_prefixes={'PATH': [sevenzip_cache_dir]}):
      yield
  else:
    yield


def CreateAndUploadFlutterPackage(api, git_hash, branch, packaging_script):
  """Prepares, builds, and uploads an all-inclusive archive package."""
  flutter_executable = 'flutter' if not api.platform.is_win else 'flutter.bat'
  dart_executable = 'dart' if not api.platform.is_win else 'dart.exe'
  work_dir = api.path['start_dir'].join('archive')
  api.step('flutter doctor', [flutter_executable, 'doctor'])
  api.step('download dependencies', [flutter_executable, 'update-packages'])
  api.file.rmtree('clean archive work directory', work_dir)
  api.file.ensure_directory('(re)create archive work directory', work_dir)
  with Install7za(api):
    with api.context(cwd=api.path['start_dir']):
      step_args = [
          dart_executable, packaging_script,
          '--temp_dir=%s' % work_dir,
          '--revision=%s' % git_hash,
          '--branch=%s' % branch
      ]
      if not api.runtime.is_experimental:
        step_args.append('--publish')
      api.step('prepare, create and publish a flutter archive', step_args)
      if api.properties.get('upload_with_cosign') is True:
        flutter_package_absolute_path = GetFlutterPackageAbsolutePath(api, work_dir)
        UploadAndSignFlutterPackage(api, flutter_package_absolute_path, git_hash, branch)


def GetFlutterPackageAbsolutePath(api, work_dir):
  """Gets full flutter package directory if it exists."""
  files = api.file.glob_paths('get flutter archive file name', work_dir, '*flutter*.tar.xz', test_data=['flutter-archive-package.tar.xz'])
  return files[0] if len(files) == 1 else None


def UploadAndSignFlutterPackage(api, flutter_path, git_hash, branch):
  """Uploads flutter package to the artifact registry, then signs it using a KMS key.
  This is all done using the package cosign.
  """
  if not api.runtime.is_experimental:
    base_artifact_registry_url = 'us-docker.pkg.dev/flutter-dashboard-dev/flutter-artifacts' # TODO(drewroen) Update production url to an actual production url
  else:
    base_artifact_registry_url = 'us-docker.pkg.dev/flutter-dashboard-dev/flutter-artifacts'

  artifact_registry_url = '%s/%s/%s/%s' % (base_artifact_registry_url, branch, git_hash, api.path.basename(flutter_path))

  gcloud_docker_config_args = [
      'gcloud',
      'auth',
      'configure-docker',
      'us-docker.pkg.dev'
  ]

  cosign_upload_args = [
      'cosign',
      'upload',
      'blob',
      '-f',
      flutter_path,
      artifact_registry_url
  ]

  cosign_sign_args = [
      'cosign',
      'sign',
      '--key',
      'gcpkms://projects/flutter-dashboard-dev/locations/global/keyRings/flutter/cryptoKeys/mykey2',
      artifact_registry_url
  ]
  api.step('configure docker registry', gcloud_docker_config_args)
  api.step('upload through cosign', cosign_upload_args)
  api.step('sign flutter artifact', cosign_sign_args)


def RunSteps(api):
  git_ref = api.properties.get('git_ref') or api.buildbucket.gitiles_commit.ref
  assert git_ref
  checkout_path = api.path['start_dir'].join('flutter')
  git_url = api.properties.get('git_url') or 'https://flutter.googlesource.com/mirrors/flutter'
  # Call this just to obtain release_git_hash so the script knows which commit
  # to release
  with api.step.nest('determine release revision'):
    release_git_hash = api.repo_util.checkout(
        'flutter',
        checkout_path=checkout_path,
        url=git_url,
        ref=git_ref,
    )
  # For creating the packages, we need to have the master branch version of the
  # script.
  with api.step.nest('checkout framework from master'):
    api.repo_util.checkout(
        'flutter',
        checkout_path=checkout_path,
        url=git_url,
        ref='master',
    )
  env, env_prefixes = api.repo_util.flutter_environment(checkout_path)
  api.flutter_deps.required_deps(
      env, env_prefixes, api.properties.get('dependencies', [])
  )
  release_ref = api.properties.get('release_ref') or git_ref

  packaging_script = checkout_path.join(
      'dev', 'bots', 'prepare_package.dart'
  )
  with api.context(env=env, env_prefixes=env_prefixes):
    with api.depot_tools.on_path():
      if release_ref:
        match = PACKAGED_REF_RE.match(release_ref)
        if match:
          branch = match.group(1)
          CreateAndUploadFlutterPackage(api, release_git_hash, branch, packaging_script)
          # Nothing left to do on a packaging branch.
          return
      raise api.step.StepFailure(
          'could not determine the release branch: either "release_ref" or "git_ref" properties should be set when manually triggering builds'
      )


def GenTests(api):
  for experimental in (True, False):
    for should_upload in (True, False):
      for platform in ('mac', 'linux', 'win'):
        for branch in ('master', 'dev', 'beta', 'stable'):
          for upload_with_cosign in (True, False):
            git_ref = 'refs/heads/' + branch
            test = api.test(
                '%s_%s%s%s%s' % (
                    platform,
                    branch,
                    '_experimental' if experimental else '',
                    '_upload' if should_upload else '',
                    '_cosign' if upload_with_cosign else ''
                ), api.platform(platform, 64),
                api.buildbucket.ci_build(git_ref=git_ref, revision=None),
                api.properties(
                    shard='tests',
                    fuchsia_ctl_version='version:0.0.2',
                    upload_packages=should_upload,
                    gold_tryjob=not should_upload,
                    upload_with_cosign=upload_with_cosign
                ), api.runtime(is_experimental=experimental),
                api.repo_util.flutter_environment_data()
            )
            yield test
