# 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

PYTHON_VERSION_COMPATIBILITY = 'PY3'

DEPS = [
    'depot_tools/gsutil',
    'flutter/osx_sdk',
    'flutter/zip',
    'recipe_engine/buildbucket',
    'recipe_engine/file',
    'recipe_engine/path',
    'recipe_engine/properties',
    'recipe_engine/runtime',
    'recipe_engine/step',
]

BUCKET_NAME = 'flutter_infra_release'

HOMEBREW_FLUTTER_PREFIX = ['flutter', 'homebrew-flutter']
MIRROR_URL_PREFIX = 'https://flutter.googlesource.com/third_party/'

INSTALL_PKGS = {
    'libplist-flutter': {
        'install_flags': ['--HEAD'],
        'deliverables': [
            'lib/libplist-2.0.3.dylib',
            'COPYING',
        ],
    },
    'usbmuxd-flutter': {
        'install_flags': ['--HEAD'],
        'deliverables': [
            'lib/libusbmuxd-2.0.6.dylib',
            'bin/iproxy',
            'COPYING',
        ],
    },
    'openssl-flutter': {
        'install_flags': ['--HEAD'],
        'deliverables': [
            'lib/libssl.1.1.dylib',
            'lib/libcrypto.1.1.dylib',
            'LICENSE',
        ],
    },
    'libimobiledevice-flutter': {
        'install_flags': ['--HEAD'],
        'deliverables': [
            'COPYING',
            'COPYING.LESSER',
            'libtasn1-LICENSE',
            'libtasn1-AUTHORS',
            'bin/idevicescreenshot',
            'bin/idevicesyslog',
            'lib/libimobiledevice-1.0.6.dylib',
        ],
    },
}


def InstallHomebrew(api, homebrew_dir):
  homebrew_tar = api.path['start_dir'].join('homebrew.tar.gz')
  api.file.ensure_directory('mkdir homebrew', homebrew_dir)
  api.step('get homebrew', [
      'curl', '-L', 'https://github.com/Homebrew/brew/tarball/master', '-o',
      homebrew_tar
  ])
  api.step('open tarball',
           ['tar', 'zxf', homebrew_tar, '--strip', '1', '-C', homebrew_dir])


def GetBrewBin(api):
  return api.path['start_dir'].join('homebrew', 'bin', 'brew')


def TapCustomBrews(api):
  api.step('tap custom formulae', [
      str(GetBrewBin(api)), 'tap', '/'.join(HOMEBREW_FLUTTER_PREFIX),
      '%s/homebrew-flutter' % MIRROR_URL_PREFIX
  ])


def GetLocalPath(api, package_name):
  return api.path['start_dir'].join('homebrew', 'opt', package_name)


def GetCloudPath(api, package_name):
  '''Location of cloud bucket for unsigned binaries'''
  commit_hash = GetCommitHash(api)
  short_name = package_name.replace('-flutter', '')
  return 'ios-usb-dependencies/unsigned/%s/%s/%s.zip' % (
      short_name, commit_hash, short_name)


def GetCommitHash(api):
  gitiles_commit = api.buildbucket.gitiles_commit.id
  if gitiles_commit:
    return gitiles_commit
  return api.properties['git_ref']


def InstallPackage(api, package, name):
  install_flags = package.get('install_flags', [])
  prefix = '/'.join(HOMEBREW_FLUTTER_PREFIX)
  api.step('installing %s' % name, [
      str(GetBrewBin(api)),
      'install',
      '/'.join([prefix, name]),
  ] + install_flags)


def CopyDeliverable(api, deliverable, name, output_path):
  deliverable_path = GetLocalPath(api, name).join(deliverable)
  api.file.copy(
      'copying %s from package %s' % (deliverable, name),
      deliverable_path,
      output_path,
  )


def ZipAndUploadDeliverables(api, package_name, input_path, zip_out_dir):
  file_name = '%s.zip' % package_name
  output_path = zip_out_dir.join(file_name)
  api.zip.directory('zipping %s' % file_name, input_path, output_path)
  cloud_path = GetCloudPath(api, package_name)
  api.step('cloud path', ['echo', cloud_path])
  api.gsutil.upload(
      output_path,
      BUCKET_NAME,
      cloud_path,
      link_name=file_name,
      name='upload of %s' % file_name,
  )


def BuildIosDeploy(api):
  build_script = api.resource('ios-deploy.sh')
  api.step('make %s executable' % build_script, ['chmod', '777', build_script])

  work_dir = api.path['start_dir']
  src_dir = work_dir.join('src')
  out_dir = work_dir.join('output')
  api.file.ensure_directory('mkdir %s' % out_dir, out_dir)
  zip_file = work_dir.join('ios-deploy.zip')
  commit_hash = GetCommitHash(api)
  api.step('build ios-deploy', [build_script, src_dir, commit_hash, out_dir])
  api.zip.directory('zipping ios-deploy dir', out_dir, zip_file)
  version_namespace = 'led' if api.runtime.is_experimental else commit_hash
  remote_path = 'ios-usb-dependencies/unsigned/ios-deploy/%s/ios-deploy.zip' % version_namespace
  api.gsutil.upload(
      zip_file,
      BUCKET_NAME,
      remote_path,
      link_name='ios-deploy.zip',
      name='upload of ios-deploy.zip',
  )


def RunSteps(api):
  with api.osx_sdk('ios'):
    package_name = api.properties['package_name']
    if package_name == 'ios-deploy-flutter':
      BuildIosDeploy(api)
    else:
      work_dir = api.path['start_dir']
      package = INSTALL_PKGS[package_name]

      homebrew_dir = work_dir.join('homebrew')
      InstallHomebrew(api, homebrew_dir)

      output_dir = work_dir.join('output')
      api.file.ensure_directory('mkdir output', output_dir)

      zip_out_dir = work_dir.join('zips')
      api.file.ensure_directory('mkdir zips', zip_out_dir)

      TapCustomBrews(api)

      InstallPackage(api, package, package_name)

      package_out_dir = output_dir.join(package_name)
      api.file.ensure_directory('mkdir package %s' % package_out_dir,
                                package_out_dir)

      if len(package['deliverables']) > 0:
        for deliverable in package['deliverables']:
          CopyDeliverable(api, deliverable, package_name, package_out_dir)

        ZipAndUploadDeliverables(api, package_name, package_out_dir,
                                 zip_out_dir)


def GenTests(api):
  yield api.test(
      'ios-deploy with git_ref',
      api.properties(
          package_name='ios-deploy-flutter',
          git_ref='deadbeef',
      ),
  )
  yield api.test(
      'ios-deploy with gitiles',
      api.properties(
          package_name='ios-deploy-flutter',
      ),
      api.buildbucket.ci_build(revision='deadbeef'),
  )
  for package_name in INSTALL_PKGS:
    yield api.test(
        package_name,
        api.properties(package_name=package_name),
        api.buildbucket.ci_build(git_ref='refs/heads/master'),
    )
