# Copyright 2023 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 recipe_engine import recipe_api

# File name inside artifacts that require signing with entitlements.
ENTITLEMENTS_FILENAME = 'entitlements.txt'
# File name inside artifacts that require signing without entitlements.
WITHOUT_ENTITLEMENTS_FILENAME = 'without_entitlements.txt'


class CodeSignApi(recipe_api.RecipeApi):
  """Provides utilities to code sign binaries in mac."""

  def __init__(self, *args, **kwargs):
    super().__init__(*args, **kwargs)
    self._initialized = False
    self._codesign_binary_path = None

  def requires_signing(self, artifact_path):
    """Validates if a file needs to be codesigned.

    Args:
      artifact_path: (str) the path to the zip file artifact
        to validate if code signing is required.

    Returns:
      True if code sign is required, False if it is not.
    """
    if not self.m.platform.is_mac:
      return False
    file_list = self.m.zip.namelist('namelist', artifact_path)
    return (
        ENTITLEMENTS_FILENAME in file_list or
        WITHOUT_ENTITLEMENTS_FILENAME in file_list
    )

  @property
  def codesign_binary(self):
    """Property pointing to the signing tool location."""
    self._ensure()
    return self._codesign_binary_path

  def _start(self, env, env_prefixes):
    self._ensure()
    self._codesign_environment(env, env_prefixes)
    self._keychain_setup(env, env_prefixes)

  def _stop(self):
    self._keychain_cleanup()

  def _ensure(self):
    if not self._codesign_binary_path:
      with self.m.step.nest('Codesign Dependencies'):
        self._codesign_binary_path = self.m.flutter_deps.codesign({}, {})

  def code_sign(self, files_to_sign):
    if not self.m.platform.is_mac:
      return
    env = {}
    env_prefixes = {}
    self.m.retry.basic_wrap(
        lambda timeout: self._start(env, env_prefixes), max_attempts=5
    )

    try:
      self._signer_tasks(env, env_prefixes, files_to_sign)
    finally:
      if not self.m.runtime.in_global_shutdown:
        self._stop()

  def _codesign_environment(self, env, env_prefixes):
    with self.m.step.nest('Setup codesign environment'):
      secrets_dict = {
          'FLUTTER_P12':
              'exported_p12.encrypted',
          'FLUTTER_P12_PASSWORD':
              '0325_p12password.encrypted',
          'CODESIGN_TEAM_ID':
              'codesign_team_id.encrypted',
          'CODESIGN_APP_SPECIFIC_PASSWORD':
              'codesign_app_specific_password.encrypted',
          'CODESIGN_APP_STORE_ID':
              'codesign_app_store_id.encrypted'
      }
      self.m.kms.decrypt_secrets(env, secrets_dict)
      env['CODESIGN_PATH'] = self.codesign_binary

  def _keychain_setup(self, env, env_prefixes):
    """KeychainSetup sets up keychain for codesign.

    This function triggers a shell script that creates a keychain named
    build.keychain. It unlocks the keychain,
    adds keychain to codesign search list, and adds flutter .p12
    to this keychain. This script also supplies p12 password,
    and grants codesign cipd and system codesign the correct access controls.
    The p12 password is hidden from stdout.

    Args:
      env (dict): environment variables.
      env_prefixes (dict) : environment paths.
    """
    with self.m.step.nest('Setup keychain'):
      resource_name = self.resource('setup_keychain.dart')
      self.m.step(
          'Set execute permission',
          ['chmod', '755', resource_name],
          infra_step=True,
      )
    # Only filepath with a .p12 suffix will be recognized.
    p12_suffix_filepath = self.m.path.cleanup_dir / 'flutter.p12'
    env['P12_SUFFIX_FILEPATH'] = p12_suffix_filepath
    setup_keychain_log_file = self.m.path.cleanup_dir / 'setup_keychain_logs.txt'

    env['SETUP_KEYCHAIN_LOGS_PATH'] = setup_keychain_log_file
    with self.m.context(env=env, env_prefixes=env_prefixes):
      self._run_keychain_setup_script(
          resource_name,
          setup_keychain_log_file,
      )

  def _run_keychain_setup_script(self, resource_name, setup_keychain_log_file):
    try:
      self.m.step(
          'run keychain setup script',
          [resource_name],
      )
    finally:
      # This will namespace the remote GCS path by the buildbucket build ID
      buildbucket_id = self.m.buildbucket.build.id

      # Setup may occur multiple times during a build. Use a unique identifier
      # so logs aren't overwritten.
      uuid = self.m.uuid.random()
      remote_path = '%s/setup_keychain_logs_%s.txt' % (buildbucket_id, uuid)
      self.m.gsutil.upload(
          bucket='flutter_tmp_logs',
          source=setup_keychain_log_file,
          dest=remote_path,
          args=['-r'],
          name='upload debug logs to %s' % remote_path
      )

  def _signer_tasks(self, env, env_prefixes, files_to_sign):
    """Concurrently creates jobs to codesign each binary.

    Args:
      env (dict): environment variables.
      env_prefixes (dict) : environment paths.
    """
    signer_builds = []
    for source_path in files_to_sign:
      signer_builds.append(
          self.m.futures.spawn(
              self._run_signer_tool_command,
              env,
              env_prefixes,
              source_path,
          )
      )

    futures = self.m.futures.wait(signer_builds)
    for future in futures:
      future.result()

  def _run_signer_tool_command(
      self,
      env,
      env_prefixes,
      source_path,
  ):
    """Runs code sign standalone app.

    Args:
      env (dict): environment variables.
      env_prefixes (dict) : environment paths.
      source_path (Path): path of the artifact to sign.
    """
    app_specific_password_filepath = env['CODESIGN_APP_SPECIFIC_PASSWORD']
    appstore_id_filepath = env['CODESIGN_APP_STORE_ID']
    team_id_filepath = env['CODESIGN_TEAM_ID']
    path, base_name = self.m.path.split(source_path)
    unsigned_path = self.m.path.join(path, 'unsigned_%s' % base_name)
    self.m.file.move('Move %s' % str(source_path), source_path, unsigned_path)
    with self.m.step.nest('Codesign %s' % str(unsigned_path)):
      flutter_certificate_name = 'Developer ID Application: FLUTTER.IO LLC (S8QB4VV633)'
      self.m.step(
          'unlock build keychain',
          ['security', 'unlock-keychain', '-p', '', 'build.keychain']
      )
      with self.m.context(env=env, env_prefixes=env_prefixes):
        self.m.step(
            'codesign Apple engine binaries',
            [
                self.codesign_binary,
                '--codesign-cert-name',
                flutter_certificate_name,
                '--no-dryrun',
                '--app-specific-password-file-path',
                app_specific_password_filepath,
                '--codesign-appstore-id-file-path',
                appstore_id_filepath,
                '--codesign-team-id-file-path',
                team_id_filepath,
                '--input-zip-file-path',
                str(unsigned_path),
                '--output-zip-file-path',
                str(source_path),
            ],
        )

  def _keychain_cleanup(self):
    """Clean up temporary keychain used in codesign process."""
    with self.m.step.nest('Keychain cleanup'):
      self.m.step(
          'delete keychain', ['security', 'delete-keychain', 'build.keychain']
      )
      self.m.step(
          'Cleanup keychain.restore default keychain',
          ['security', 'default-keychain', '-s', 'login.keychain']
      )
