# 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/(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
  ]

  ## The force parameter bypasses the confirmation prompt from cosign
  cosign_sign_args = [
      'cosign',
      'sign',
      artifact_registry_url,
      '--force'
  ]
  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)

  # TODO(drewroen): Remove this once cosign supports keyless signing without enabling
  # experimental features.
  if api.properties.get('upload_with_cosign') is True:
    env['COSIGN_EXPERIMENTAL'] = 'true'

  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', '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
