import os
import re
import subprocess
import sys
import time

# Initial number of seconds to wait before retrying a command.
INITIAL_BACKOFF = 2

# Number of retries when a command fails.
RETRIES = 3

# Assets located here.
ASSET_DIR = '/usr/local/share/assets'

# Directory where the dev images are.
DEV_IMG_DIR = ASSET_DIR + '/devimages'

# Path to the provisioning profile.
PROVISIONING_PROF = ASSET_DIR + '/development.mobileprovision'

# Fields that should be ignored when getting the iOS device info
IGNORE_FIELDS = set([
  'CompassCalibration'
  'ProximitySensorCalibration'
  'SoftwareBehavior'
])


def ios_get_device_ids():
  """Returns the ids of all attached devices.

     This will also work when the attached device is not fully booted."""
  ret = []
  # Primary purpose of this, is to catch when the tools are not installed.
  try:
    output = _run_cmd('idevice_id --list')
    for line in output.splitlines():
      if line.strip():
        ret.append(line.strip())
  except (IOError, OSError, subprocess.CalledProcessError):
    pass
  return ret


def ios_get_devices():
  """Returns instances of IOSDevice for each attached device."""
  return [IOSDevice(x) for x in ios_get_device_ids()]


class IOSDevice(object):
  def __init__(self, dev_id):
    self._id = dev_id

  def get_state(self):
    """Returns a dictionary to be used"""
    return _get_kv_pairs(_run_cmd('ideviceinfo -u %s' % self._id))

  def get_battery_state(self):
    cmd = "ideviceinfo -u %s -q %s" % (self._id, 'com.apple.mobile.battery')
    return _get_kv_pairs(_run_cmd(cmd))

  def reboot(self):
    """Reboots the device."""
    _run_cmd('idevicediagnostics restart -u %s' % self._id)

  def get_ready(self):
    """Does all the necessary setup to run apps on the device."""
    # Pair the device with the host.
    ret = _run_ret_value('idevicepair -u %s validate' % self._id)
    if ret != 0:
      _run_cmd('idevicepair -u %s pair' % self._id)

    # Check if a developer images has been mounted already.
    kv = _get_kv_pairs(_run_cmd('ideviceimagemounter -u %s -l' % self._id))

    # Check if there is an image present.
    if not ((kv.get('ImagePresent', '') == 'true') or
            kv.get('ImageSignature', [])):
      # Mount the developer image.
      img, imgSig = self._get_dev_image()
      cmd = ['ideviceimagemounter', '-u', self._id, img, imgSig]
      kv = _get_kv_pairs(_run_cmd(cmd))
      assert(kv['Status'] == 'Complete')

    # Install the provisioning profile.
    _run_cmd('ideviceprovision -u %s remove-all' % self._id)
    cmd = 'ideviceprovision -u %s install %s' % (self._id, PROVISIONING_PROF)
    _run_cmd(cmd)


  def _get_dev_image(self):
    # Get the version of the device
    state = self.get_state()
    ver = state['ProductVersion'].split('.', 2)[:2]
    prefix = '.'.join(ver)

    # iterate over the contents of the image dir and find the right image
    for dirname in os.listdir(DEV_IMG_DIR):
      path = os.path.join(DEV_IMG_DIR, dirname)
      if os.path.isdir(path) and dirname.startswith(prefix):
        contents = os.listdir(path)
        devImage = [x for x in contents if x.endswith('.dmg')][0]
        devImageSig = [x for x in contents if x.endswith('.dmg.signature')][0]
        return os.path.join(path, devImage), os.path.join(path, devImageSig)
    raise ValueError('Unable to find dev images.')


# Utility functions.
def _get_kv_pairs(output):
  """Extract key/value pairs from output."""
  ret = {}
  nested = None
  # Note: This assumes that there is at most one level of nesting
  # arrays or dictionaries.
  for line in output.splitlines():
    if line.strip():
      split_line = line.split(":", 1)
      if len(split_line) < 2:
        continue

      k,v = [x.strip() for x in split_line]
      if line.startswith(' '):
        if isinstance(nested, dict):
          nested[k] = v
        else:
          nested.append(v)
      else:
        # If the value is an array it has this format: key_name[x]
        # where x is an integer indicating the number of elements.
        m = re.match(r'^(.*)\[[0-9]*\]$', k)
        if m:
          k = m.group(1)
          nested = []
          v = nested
        # If 'v' is empty then we expect a hash map.
        elif v == '':
          nested = {}
          v = nested
        ret[k] = v
  return ret


def _run_ret_value(cmd):
  """ Run the given command and return the exit status"""
  try:
    _run_cmd(cmd)
    return 0
  except subprocess.CalledProcessError as ex:
    return ex.returncode


def _run_cmd(cmd):
  """Run the given command and return the output.

  Returns:
    Output from the command as a string.

  Raises:
    subprocess.CalledProcessError: If the global number of retries is
    exceeded."""
  backoff = INITIAL_BACKOFF
  retry = 0
  while True:
    try:
      args = cmd if isinstance(cmd, list) else cmd.strip().split()
      output = subprocess.check_output(args, stderr=sys.stderr)
      return output
    except subprocess.CalledProcessError:
      retry += 1
      if retry >= RETRIES:
        raise
      time.sleep(backoff)
      backoff *= 2

# TODO(stephana): Move the main program below into a separate script
# or into the skia repo entirely.

if __name__=='__main__':
  dev = ios_get_devices()[0]
  dev.get_ready()
  print "Successfully set up device."
