# Copyright 2017 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 . import default


"""iOS flavor, used for running code on iOS."""


class iOSFlavor(default.DefaultFlavor):
  def __init__(self, m, app_name):
    super(iOSFlavor, self).__init__(m, app_name)
    self.device_dirs = default.DeviceDirs(
        bin_dir='[unused]',
        dm_dir='dm',
        perf_data_dir='perf',
        resource_dir='resources',
        images_dir='images',
        lotties_dir='lotties',
        skp_dir='skps',
        svg_dir='svgs',
        mskp_dir='mskp',
        tmp_dir='tmp',
        texttraces_dir='')

  @property
  def env(self):
    return {
      'IOS_BUNDLE_ID': 'com.google.%s' % self.app_name,
      'IOS_MOUNT_POINT': self.m.vars.workdir.join('mnt_iosdevice'),
    }

  def context(self):
    return self.m.context(env=self.env)

  def _run(self, title, *cmd, **kwargs):
    def sleep(attempt):
      self.m.python.inline('sleep before attempt %d' % attempt, """
import time
time.sleep(2)
""")  # pragma: nocover
    return self.m.run.with_retry(self.m.step, title, 3, cmd=list(cmd),
                                 between_attempts_fn=sleep, **kwargs)

  def install(self):
    with self.context():
      self._install()

  def _install(self):
    # We assume a single device is connected.

    # Pair the device.
    try:
      self.m.run(self.m.step, 'check if device is paired',
                 cmd=['idevicepair', 'validate'],
                 infra_step=True, abort_on_failure=True,
                 fail_build_on_failure=False)
    except self.m.step.StepFailure:  # pragma: nocover
      self._run('pair device', 'idevicepair', 'pair')  # pragma: nocover

    # Mount developer image.
    image_info = self._run('list mounted image',
                           'ideviceimagemounter', '--list',
                           stdout=self.m.raw_io.output())
    image_info_out = image_info.stdout.strip() if image_info.stdout else ''

    if 'ImageSignature' not in image_info_out:
      image_pkgs = self.m.file.glob_paths('locate ios-dev-image package',
                                          self.m.path['start_dir'],
                                          'ios-dev-image*',
                                          test_data=['ios-dev-image-13.2'])
      if len(image_pkgs) != 1:
        raise Exception('glob for ios-dev-image* returned %s'
                        % image_pkgs)  # pragma: nocover

      image_pkg = image_pkgs[0]
      contents = self.m.file.listdir(
          'locate image and signature', image_pkg,
          test_data=['DeveloperDiskImage.dmg',
                     'DeveloperDiskImage.dmg.signature'])
      image = None
      sig = None
      for f in contents:
        if str(f).endswith('.dmg'):
          image = f
        if str(f).endswith('.dmg.signature'):
          sig = f
      if not image or not sig:
        raise Exception('%s does not contain *.dmg and *.dmg.signature' %
                        image_pkg)  # pragma: nocover

      self._run('mount developer image', 'ideviceimagemounter', image, sig)

    # Install app (necessary before copying any resources to the device).
    if self.app_name:
      app_package = self.host_dirs.bin_dir.join('%s.app' % self.app_name)

      def uninstall_app(attempt):
        # If app ID changes, upgrade will fail, so try uninstalling.
        self.m.run(self.m.step,
                   'uninstall %s' % self.app_name,
                   cmd=['ideviceinstaller', '-U',
                        'com.google.%s' % self.app_name],
                   infra_step=True,
                   # App may not be installed.
                   abort_on_failure=False, fail_build_on_failure=False)

      num_attempts = 2
      self.m.run.with_retry(self.m.step, 'install %s' % self.app_name,
                            num_attempts,
                            cmd=['ideviceinstaller', '-i', app_package],
                            between_attempts_fn=uninstall_app,
                            infra_step=True)

  def step(self, name, cmd, **kwargs):
    app_name = cmd[0]
    bundle_id = 'com.google.%s' % app_name
    args = [bundle_id] + map(str, cmd[1:])
    success = False
    with self.context():
      try:
        self.m.run(self.m.step, name, cmd=['idevicedebug', 'run'] + args)
        success = True
      finally:
        if not success:
          self.m.run(self.m.python, '%s with full debug output' % name,
                     script=self.module.resource('ios_debug_cmd.py'),
                     args=args)

  def _run_ios_script(self, script, first, *rest):
    with self.context():
      full = self.m.path['start_dir'].join(
          'skia', 'platform_tools', 'ios', 'bin', 'ios_' + script)
      self.m.run(self.m.step,
                 name = '%s %s' % (script, first),
                 cmd = [full, first] + list(rest),
                 infra_step=True)

  def copy_file_to_device(self, host, device):
    self._run_ios_script('push_file', host, device)

  def copy_directory_contents_to_device(self, host, device):
    self._run_ios_script('push_if_needed', host, device)

  def copy_directory_contents_to_host(self, device, host):
    self._run_ios_script('pull_if_needed', device, host)

  def remove_file_on_device(self, path):
    self._run_ios_script('rm', path)

  def create_clean_device_dir(self, path):
    self._run_ios_script('rm',    path)
    self._run_ios_script('mkdir', path)

  def read_file_on_device(self, path, **kwargs):
    with self.context():
      full = self.m.path['start_dir'].join(
          'skia', 'platform_tools', 'ios', 'bin', 'ios_cat_file')
      rv = self.m.run(self.m.step,
                      name = 'cat_file %s' % path,
                      cmd = [full, path],
                      stdout=self.m.raw_io.output(),
                      infra_step=True,
                      **kwargs)
      return rv.stdout.rstrip() if rv and rv.stdout else None
