#!/usr/bin/env python
# Copyright 2015 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.

import argparse
import atexit
import errno
import json
import logging
import os
import platform
import random
import re
import signal
import socket
import subprocess
import sys
import tempfile
import time
import urlparse

PACKAGES_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
SKY_ENGINE_DIR = os.path.join(PACKAGES_DIR, 'sky_engine')
APK_DIR = os.path.join(os.path.realpath(SKY_ENGINE_DIR), os.pardir, 'apks')

SKY_SERVER_PORT = 9888
OBSERVATORY_PORT = 8181
ADB_PATH = 'adb'
APK_NAME = 'SkyShell.apk'
ANDROID_PACKAGE = 'org.domokit.sky.shell'
ANDROID_COMPONENT = '%s/%s.SkyActivity' % (ANDROID_PACKAGE, ANDROID_PACKAGE)

SKY_SHELL_APP_ID = 'com.google.SkyShell'
IOS_APP_NAME = 'SkyShell.app'

# FIXME: Do we need to look in $DART_SDK?
DART_PATH = 'dart'
PUB_PATH = 'pub'

PID_FILE_PATH = '/tmp/sky_tool.pids'
PID_FILE_KEYS = frozenset([
    'remote_sky_server_port',
    'sky_server_pid',
    'sky_server_port',
    'sky_server_root',
])

IOS_SIM_PATH = [
    os.path.join('/Applications', 'iOS Simulator.app', 'Contents', 'MacOS', 'iOS Simulator')
]

XCRUN_PATH = [
    os.path.join('/usr', 'bin', 'env'),
    'xcrun',
]

SIMCTL_PATH = XCRUN_PATH + [
    'simctl',
]

PLIST_BUDDY_PATH = XCRUN_PATH + [
    'PlistBuddy',
]


def _port_in_use(port):
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    return sock.connect_ex(('localhost', port)) == 0


def _start_http_server(port, root):
    server_command = [
        PUB_PATH, 'run', 'sky_tools:sky_server', str(port),
    ]
    return subprocess.Popen(server_command, cwd=root).pid


# This 'strict dictionary' approach is useful for catching typos.
class Pids(object):
    def __init__(self, known_keys, contents=None):
        self._known_keys = known_keys
        self._dict = contents if contents is not None else {}

    def __len__(self):
        return len(self._dict)

    def get(self, key, default=None):
        assert key in self._known_keys, '%s not in known_keys' % key
        return self._dict.get(key, default)

    def __getitem__(self, key):
        assert key in self._known_keys, '%s not in known_keys' % key
        return self._dict[key]

    def __setitem__(self, key, value):
        assert key in self._known_keys, '%s not in known_keys' % key
        self._dict[key] = value

    def __delitem__(self, key):
        assert key in self._known_keys, '%s not in known_keys' % key
        del self._dict[key]

    def __iter__(self):
        return iter(self._dict)

    def __contains__(self, key):
        assert key in self._known_keys, '%s not in allowed_keys' % key
        return key in self._dict

    def clear(self):
        self._dict = {}

    def pop(self, key, default=None):
        assert key in self._known_keys, '%s not in known_keys' % key
        return self._dict.pop(key, default)

    @classmethod
    def read_from(cls, path, known_keys):
        contents = {}
        try:
            with open(path, 'r') as pid_file:
                contents = json.load(pid_file)
        except:
            if os.path.exists(path):
                logging.warn('Failed to read pid file: %s' % path)
        return cls(known_keys, contents)

    def write_to(self, path):
        # These keys are required to write a valid file.
        if not self._dict.viewkeys() >= { 'sky_server_pid', 'sky_server_port' }:
            return

        try:
            with open(path, 'w') as pid_file:
                json.dump(self._dict, pid_file, indent=2, sort_keys=True)
        except:
            logging.warn('Failed to write pid file: %s' % path)


def _url_for_path(port, root, path):
    relative_path = os.path.relpath(path, root)
    return 'http://localhost:%s/%s' % (port, relative_path)


class StartSky(object):
    def add_subparser(self, subparsers):
        start_parser = subparsers.add_parser('start',
            help='launch %s on the device' % APK_NAME)
        start_parser.add_argument('--install', action='store_true')
        start_parser.add_argument('--poke', action='store_true')
        start_parser.add_argument('--checked', action='store_true')
        start_parser.add_argument('project_or_path', nargs='?', type=str,
            default='.')
        start_parser.set_defaults(func=self.run)

    def _is_package_installed(self, package_name):
        pm_path_cmd = [ADB_PATH, 'shell', 'pm', 'path', package_name]
        return subprocess.check_output(pm_path_cmd).strip() != ''

    def _is_valid_script_path(self):
        script_path = os.path.dirname(os.path.abspath(__file__))
        script_dirs = script_path.split('/')
        return len(script_dirs) > 1 and script_dirs[-2] == 'packages'

    def run(self, args, pids):
        if not args.poke:
            StopSky().run(args, pids)

        project_or_path = os.path.abspath(args.project_or_path)

        if os.path.isdir(project_or_path):
            sky_server_root = project_or_path
            main_dart = os.path.join(project_or_path, 'lib', 'main.dart')
            missing_msg = 'Missing lib/main.dart in project: %s' % project_or_path
        else:
            # FIXME: This assumes the path is at the root of the project!
            # Instead we should walk up looking for a pubspec.yaml
            sky_server_root = os.path.dirname(project_or_path)
            main_dart = project_or_path
            missing_msg = '%s does not exist.' % main_dart

        if not os.path.isfile(main_dart):
            logging.error(missing_msg)
            return 2

        package_root = os.path.join(sky_server_root, 'packages')
        if not os.path.isdir(package_root):
            logging.error('%s is not a valid packages path.' % package_root)
            return 2

        if not self._is_package_installed(ANDROID_PACKAGE):
            logging.info('%s is not on the device. Installing now...' % APK_NAME)
            args.install = True

        if args.install:
            if not self._is_valid_script_path():
                logging.error('"%s" must be located in packages/sky. '
                              'The directory packages/sky_engine must also '
                              'exist to locate %s.' % (os.path.basename(__file__), APK_NAME))
                return 2
            if args.local_build:
                apk_path = os.path.join(os.path.normpath(args.sky_src_path), args.android_debug_build_path, 'apks', APK_NAME)
            else:
                apk_path = os.path.join(APK_DIR, APK_NAME)
            if not os.path.exists(apk_path):
                logging.error('"%s" does not exist.' % apk_path)
                return 2

            cmd = [ADB_PATH, 'install', '-r', apk_path]
            subprocess.check_call(cmd)

            # Install on connected iOS device
            if IOSDevice.is_connected() and args.local_build:
                app_path = os.path.join(args.sky_src_path, args.ios_debug_build_path, IOS_APP_NAME)
                IOSDevice.install_app(app_path)

            # Install on iOS simulator if it's running
            if IOSSimulator.is_booted() and args.local_build:
                app_path = os.path.join(args.sky_src_path, args.ios_sim_debug_build_path, IOS_APP_NAME)
                IOSSimulator.fork_install_app(app_path)

        # Set up port forwarding for observatory
        observatory_port_string = 'tcp:%s' % OBSERVATORY_PORT
        subprocess.check_call([
            ADB_PATH, 'forward', observatory_port_string, observatory_port_string
        ])

        sky_server_port = SKY_SERVER_PORT
        pids['sky_server_port'] = sky_server_port
        if _port_in_use(sky_server_port):
            logging.info(('Port %s already in use. '
            ' Not starting server for %s') % (sky_server_port, sky_server_root))
        else:
            sky_server_pid = _start_http_server(sky_server_port, sky_server_root)
            pids['sky_server_pid'] = sky_server_pid
            pids['sky_server_root'] = sky_server_root

        port_string = 'tcp:%s' % sky_server_port
        subprocess.check_call([
            ADB_PATH, 'reverse', port_string, port_string
        ])
        pids['remote_sky_server_port'] = sky_server_port

        # The load happens on the remote device, use the remote port.
        url = _url_for_path(pids['remote_sky_server_port'], sky_server_root,
            main_dart)
        if args.poke:
            url += '?rand=%s' % random.random()

        cmd = [
            ADB_PATH, 'shell',
            'am', 'start',
            '-a', 'android.intent.action.VIEW',
            '-d', url,
        ]

        if args.checked:
            cmd += [ '--ez', 'enable-checked-mode', 'true' ]

        cmd += [ ANDROID_COMPONENT ]

        subprocess.check_output(cmd)


class StopSky(object):
    def add_subparser(self, subparsers):
        stop_parser = subparsers.add_parser('stop',
            help=('kill all running SkyShell.apk processes'))
        stop_parser.set_defaults(func=self.run)

    def _run(self, args):
        with open('/dev/null', 'w') as dev_null:
            subprocess.call(args, stdout=dev_null, stderr=dev_null)

    def run(self, args, pids):
        self._run(['fuser', '-k', '%s/tcp' % SKY_SERVER_PORT])

        if 'remote_sky_server_port' in pids:
            port_string = 'tcp:%s' % pids['remote_sky_server_port']
            self._run([ADB_PATH, 'reverse', '--remove', port_string])

        self._run([ADB_PATH, 'shell', 'am', 'force-stop', ANDROID_PACKAGE])

        pids.clear()


class IOSDevice(object):
    _has_ios_deploy = None
    @classmethod
    def has_ios_deploy(cls):
        if cls._has_ios_deploy is not None:
            return cls._has_ios_deploy
        try:
            cmd = [
                'which',
                'ios-deploy'
            ]
            out = subprocess.check_output(cmd)
            match = re.search(r'ios-deploy', out)
            cls._has_ios_deploy = match is not None
        except subprocess.CalledProcessError:
            cls._has_ios_deploy = False
        return cls._has_ios_deploy

    _is_connected = False
    @classmethod
    def is_connected(cls):
        if not cls.has_ios_deploy():
            return False
        if cls._is_connected:
            return True
        cmd = [
            'ios-deploy',
            '--detect',
            '--timeout',
            '1'
        ]
        out = subprocess.check_output(cmd)
        match = re.search(r'\[\.\.\.\.\] Found [^\)]*\) connected', out)
        cls._is_connected = match is not None
        return cls._is_connected

    @classmethod
    def install_app(cls, ios_app_path):
        if not cls.has_ios_deploy():
            return
        cmd = [
            'ios-deploy',
            '--justlaunch',
            '--timeout',
            '10', # Smaller timeouts cause it to exit before having launched the app
            '--bundle',
            ios_app_path
        ]
        subprocess.check_call(cmd)

    @classmethod
    def copy_file(cls, bundle_id, local_path, device_path):
        if not cls.has_ios_deploy():
            return
        cmd = [
            'ios-deploy',
            '-t',
            '1',
            '--bundle_id',
            bundle_id,
            '--upload',
            local_path,
            '--to',
            device_path
        ]
        subprocess.check_call(cmd)


class IOSSimulator(object):
    @classmethod
    def is_booted(cls):
        if platform.system() != 'Darwin':
            return False
        return cls.get_simulator_device_id() is not None

    _device_id = None
    @classmethod
    def get_simulator_device_id(cls):
        if cls._device_id is not None:
            return cls._device_id
        cmd = SIMCTL_PATH + [
            'list',
            'devices',
        ]
        out = subprocess.check_output(cmd)
        match = re.search(r'[^\(]+\(([^\)]+)\) \(Booted\)', out)
        if match is not None and match.group(1) is not None:
            cls._device_id = match.group(1)
            return cls._device_id
        else:
            logging.warning('No running simulators found')
            # TODO: Maybe start the simulator?
            return None
        if err is not None:
            print(err)
            exit(-1)

    _simulator_path = None
    @classmethod
    def get_simulator_path(cls):
        if cls._simulator_path is not None:
            return cls._simulator_path
        home_dir = os.path.expanduser('~')
        device_id = cls.get_simulator_device_id()
        if device_id is None:
            # TODO: Maybe start the simulator?
            return None
        cls._simulator_path = os.path.join(home_dir, 'Library', 'Developer', 'CoreSimulator', 'Devices', device_id)
        return cls._simulator_path

    _simulator_app_id = None
    @classmethod
    def get_simulator_app_id(cls):
        if cls._simulator_app_id is not None:
            return cls._simulator_app_id
        simulator_path = cls.get_simulator_path()
        cmd = [
            'find',
            os.path.join(simulator_path, 'data', 'Containers', 'Data', 'Application'),
            '-name',
            SKY_SHELL_APP_ID
        ]
        out = subprocess.check_output(cmd)
        match = re.search(r'Data\/Application\/([^\/]+)\/Documents\/' + SKY_SHELL_APP_ID, out)
        if match is not None and match.group(1) is not None:
            cls._simulator_app_id = match.group(1)
            return cls._simulator_app_id
        else:
            logging.warning(SKY_SHELL_APP_ID + ' is not installed on the simulator')
            # TODO: Maybe install the app?
            return None
        if err is not None:
            print(err)
            exit(-1)

    _simulator_app_documents_dir = None
    @classmethod
    def get_simulator_app_documents_dir(cls):
        if cls._simulator_app_documents_dir is not None:
            return cls._simulator_app_documents_dir
        if not cls.is_booted():
            return None
        simulator_path = cls.get_simulator_path()
        simulator_app_id = cls.get_simulator_app_id()
        if simulator_app_id is None:
            return None
        cls._simulator_app_documents_dir = os.path.join(simulator_path, 'data', 'Containers', 'Data', 'Application', simulator_app_id, 'Documents')
        return cls._simulator_app_documents_dir

    @classmethod
    def fork_install_app(cls, ios_app_path):
        cmd = [
            os.path.abspath(__file__),
            'ios_sim',
            '-p',
            # This path manipulation is to work around an issue where simctl fails to correctly parse
            # paths that start with ../
            ios_app_path,
            'launch'
        ]
        subprocess.check_call(cmd)

    def get_application_identifier(self, path):
      identifier = subprocess.check_output(PLIST_BUDDY_PATH + [
        '-c',
        'Print CFBundleIdentifier',
        os.path.join(path, 'Info.plist')
      ])
      return identifier.strip()

    def is_simulator_booted(self):
      devices = subprocess.check_output(SIMCTL_PATH + [ 'list', 'devices' ]).strip().split('\n')
      for device in devices:
        if re.search(r'\(Booted\)', device):
          return True
      return False

    # Launch whatever simulator the user last used, rather than try to guess which of their simulators they might want to use
    def boot_simulator(self, args, pids):
      if self.is_simulator_booted():
        return
      # Use Popen here because launching the simulator from the command line in this manner doesn't return, so we can't check the result.
      if args.ios_sim_path:
        subprocess.Popen(args.ios_sim_path)
      else:
        subprocess.Popen(IOS_SIM_PATH)
      while not self.is_simulator_booted():
        print('Waiting for iOS Simulator to boot...')
        time.sleep(0.5)

    def install_app(self, args, pids):
      self.boot_simulator(args, pids)
      cmd = SIMCTL_PATH + [
        'install',
        'booted',
        args.path,
      ]
      return subprocess.check_call(cmd)

    def install_launch_and_wait(self, args, pids, wait):
      res = self.install_app(args, pids)
      if res != 0:
        return res
      identifier = self.get_application_identifier(args.path)
      launch_args = [ 'launch' ]
      if wait:
        launch_args += [ '-w' ]
      launch_args += [
        'booted',
        identifier,
        '-target',
        args.target,
        '-server',
        args.server
      ]
      return subprocess.check_output(SIMCTL_PATH + launch_args).strip()

    def launch_app(self, args, pids):
      self.install_launch_and_wait(args, pids, False)

    def debug_app(self, args, pids):
      launch_res = self.install_launch_and_wait(args, pids, True)
      launch_pid = re.search('.*: (\d+)', launch_res).group(1)
      return os.system(' '.join(XCRUN_PATH + [
        'lldb',
        # TODO(iansf): get this working again
        # '-s',
        # os.path.join(os.path.dirname(__file__), 'lldb_start_commands.txt'),
        '-p',
        launch_pid,
      ]))

    def add_subparser(self, subparsers):
        simulator_parser = subparsers.add_parser('ios_sim',
            help='A script that launches an'
                 ' application in the simulator and attaches'
                 ' the debugger to it.')
        simulator_parser.add_argument('-p', dest='path', required=True,
            help='Path to the simulator application.')
        simulator_parser.add_argument('-t', dest='target', required=False,
            default='examples/demo_launcher/lib/main.dart',
            help='Sky server-relative path to the Sky app to run.')
        simulator_parser.add_argument('-s', dest='server', required=False,
            default='localhost:8080',
            help='Sky server address.')
        simulator_parser.add_argument('--ios_sim_path', dest='ios_sim_path',
            help='Path to your iOS Simulator executable. '
                 'Not normally required.')

        subparsers = simulator_parser.add_subparsers()
        launch_parser = subparsers.add_parser('launch', help='Launch app')
        launch_parser.set_defaults(func=self.launch_app)
        install_parser = subparsers.add_parser('install', help='Install app')
        install_parser.set_defaults(func=self.install_app)
        debug_parser = subparsers.add_parser('debug', help='Debug app')
        debug_parser.set_defaults(func=self.debug_app)

    def run(self, args, pids):
      return args.func(args)


class StartListening(object):
    def __init__(self):
        self.watch_cmd = None

    def add_subparser(self, subparsers):
        listen_parser = subparsers.add_parser('listen',
            help=('Listen for changes to files and reload the running app on all connected devices'))
        listen_parser.set_defaults(func=self.run)

    def watch_dir(self, directory):
        if self.watch_cmd is None:
            name = platform.system()
            if name == 'Linux':
                try:
                    cmd = [
                        'which',
                        'inotifywait'
                    ]
                    out = subprocess.check_output(cmd)
                except subprocess.CalledProcessError:
                    logging.error('"listen" command is only useful if you have installed inotifywait on Linux.  Run "apt-get install inotify-tools" or equivalent to install it.')
                    return False

                self.watch_cmd = [
                    'inotifywait',
                    '-r',
                    '-e',
                    'modify,close_write,move,create,delete', # Only listen for events that matter, to avoid triggering constantly from the editor watching files
                    directory
                ]
            elif name == 'Darwin':
                try:
                    cmd = [
                        'which',
                        'fswatch'
                    ]
                    out = subprocess.check_output(cmd)
                except subprocess.CalledProcessError:
                    logging.error('"listen" command is only useful if you have installed fswatch on Mac.  Run "brew install fswatch" to install it with homebrew.')
                    return False

                self.watch_cmd = [
                    'fswatch',
                    '-r',
                    '-v',
                    '-1',
                    directory
                ]
            else:
                logging.error('"listen" command is only available on Mac and Linux.')
                return False

        subprocess.check_call(self.watch_cmd)
        return True

    def run(self, args, pids):
        tempdir = tempfile.mkdtemp()
        currdir = os.getcwd()
        while True:
            # Watch filesystem for changes
            if not self.watch_dir(currdir):
                return

            logging.info('Updating running Sky apps...')

            # Restart the app on Android.  Android does not currently restart using skyx files.
            cmd = [
                sys.executable,
                os.path.abspath(__file__),
                'start',
                '--poke'
            ]
            subprocess.check_call(cmd)

            if not args.local_build:
                # Currently sending to iOS only works if you are building Sky locally
                # since we aren't shipping the sky_snapshot binary yet.
                continue

            # Build the snapshot
            sky_snapshot_path = os.path.join(args.sky_src_path, args.ios_sim_debug_build_path, 'clang_x64', 'sky_snapshot')
            cmd = [
                sky_snapshot_path,
                '--package-root=packages',
                '--snapshot=' + os.path.join(tempdir, 'snapshot_blob.bin'),
                os.path.join('lib', 'main.dart')
            ]
            subprocess.check_call(cmd)

            os.chdir(tempdir)
            # Turn the snapshot into an app.skyx file
            cmd = [
                'zip',
                '-r',
                'app.skyx',
                'snapshot_blob.bin',
                'action',
                'content',
                'navigation'
            ]
            subprocess.check_call(cmd)
            os.chdir(currdir)

            # Copy the app.skyx to the running simulator
            simulator_app_documents_dir = IOSSimulator.get_simulator_app_documents_dir()
            if simulator_app_documents_dir is not None:
                cmd = [
                    'cp',
                    os.path.join(tempdir, 'app.skyx'),
                    simulator_app_documents_dir
                ]
                subprocess.check_call(cmd)

            # Copy the app.skyx to the attached iOS device
            if IOSDevice.is_connected():
                IOSDevice.copy_file(SKY_SHELL_APP_ID, os.path.join(tempdir, 'app.skyx'), 'Documents/app.skyx')


class StartTracing(object):
    def add_subparser(self, subparsers):
        start_tracing_parser = subparsers.add_parser('start_tracing',
            help=('start tracing a running sky instance'))
        start_tracing_parser.set_defaults(func=self.run)

    def run(self, args, pids):
        subprocess.check_output([ADB_PATH, 'shell',
            'am', 'broadcast',
            '-a', 'org.domokit.sky.shell.TRACING_START'])


TRACE_COMPLETE_REGEXP = re.compile('Trace complete')
TRACE_FILE_REGEXP = re.compile(r'Saving trace to (?P<path>\S+)')


class StopTracing(object):
    def add_subparser(self, subparsers):
        stop_tracing_parser = subparsers.add_parser('stop_tracing',
            help=('stop tracing a running sky instance'))
        stop_tracing_parser.set_defaults(func=self.run)

    def run(self, args, pids):
        subprocess.check_output([ADB_PATH, 'logcat', '-c'])
        subprocess.check_output([ADB_PATH, 'shell',
            'am', 'broadcast',
            '-a', 'org.domokit.sky.shell.TRACING_STOP'])
        device_path = None
        is_complete = False
        while not is_complete:
            time.sleep(0.2)
            log = subprocess.check_output([ADB_PATH, 'logcat', '-d'])
            if device_path is None:
                result = TRACE_FILE_REGEXP.search(log)
                if result:
                    device_path = result.group('path')
            is_complete = TRACE_COMPLETE_REGEXP.search(log) is not None

        logging.info('Downloading trace %s ...' % os.path.basename(device_path))

        if device_path:
            subprocess.check_output([ADB_PATH, 'pull', device_path])
            subprocess.check_output([ADB_PATH, 'shell', 'rm', device_path])


class SkyShellRunner(object):
    def _update_paths(self):
        global ADB_PATH
        if 'ANDROID_HOME' in os.environ:
            android_home_dir = os.environ['ANDROID_HOME']
            ADB_PATH = os.path.join(android_home_dir, 'sdk', 'platform-tools', 'adb')

    def _is_valid_adb_version(self, adb_version):
        # Sample output: 'Android Debug Bridge version 1.0.31'
        version_fields = re.search('(\d+)\.(\d+)\.(\d+)', adb_version)
        if version_fields:
            major_version = int(version_fields.group(1))
            minor_version = int(version_fields.group(2))
            patch_version = int(version_fields.group(3))
            if major_version > 1:
                return True
            if major_version == 1 and minor_version > 0:
                return True
            if major_version == 1 and minor_version == 0 and patch_version >= 32:
                return True
            return False
        else:
            logging.warn('Unrecognized adb version string. Skipping version check.')
            return True

    def _check_for_adb(self):
        try:
            adb_version = subprocess.check_output([ADB_PATH, 'version'])
            if self._is_valid_adb_version(adb_version):
                return True

            adb_path = subprocess.check_output(['which', ADB_PATH]).rstrip()
            logging.error('"%s" is too old. Need 1.0.32 or later. '
                'Try setting ANDROID_HOME.' % adb_path)
            return False

        except OSError:
            logging.error('"adb" (from the Android SDK) not in $PATH, cannot continue.')
            return False
        return True

    def _check_for_lollipop_or_later(self):
        try:
            # If the server is automatically restarted, then we get irrelevant
            # output lines like this, which we want to ignore:
            #   adb server is out of date.  killing..
            #   * daemon started successfully *

            subprocess.call([ADB_PATH, 'start-server'])
            sdk_version = subprocess.check_output(
                    [ADB_PATH, 'shell', 'getprop', 'ro.build.version.sdk']).rstrip()
            # Sample output: '22'
            if not sdk_version.isdigit():
                logging.error('Unexpected response from getprop: "%s".' % sdk_version)
                return False

            if int(sdk_version) < 22:
                logging.error('Version "%s" of the Android SDK is too old. '
                              'Need Lollipop (22) or later. ' % sdk_version)
                return False

        except subprocess.CalledProcessError as e:
            # adb printed the error, so we print nothing.
            return False
        return True

    def _check_for_dart(self):
        try:
            subprocess.check_output([DART_PATH, '--version'], stderr=subprocess.STDOUT)
        except OSError:
            logging.error('"dart" (from the Dart SDK) not in $PATH, cannot continue.')
            return False
        return True

    def main(self):
        logging.basicConfig(format='%(levelname)s:%(message)s', level=logging.INFO)

        self._update_paths()
        if not self._check_for_adb() or not self._check_for_lollipop_or_later():
            sys.exit(2)
        if not self._check_for_dart():
            sys.exit(2)

        parser = argparse.ArgumentParser(description='Sky App Runner')
        parser.add_argument('--local-build', dest='local_build', action='store_true',
            help='Set this if you are building Sky locally and want to use those build products. '
                 'When set, attempts to automaticaly determine sky-src-path if sky-src-path is '
                 'not set. Not normally required.')
        parser.add_argument('--sky-src-path', dest='sky_src_path',
            help='Path to your Sky src directory, if you are building Sky locally. '
                 'Ignored if local-build is not set. Not normally required.')
        parser.add_argument('--android-debug-build-path', dest='android_debug_build_path',
            help='Path to your Android Debug out directory, if you are building Sky locally. '
                 'This path is relative to sky-src-path. Not normally required.',
            default='out/android_Debug/')
        parser.add_argument('--ios-debug-build-path', dest='ios_debug_build_path',
            help='Path to your iOS Debug out directory, if you are building Sky locally. '
                 'This path is relative to sky-src-path. Not normally required.',
            default='out/ios_Debug/')
        parser.add_argument('--ios-sim-debug-build-path', dest='ios_sim_debug_build_path',
            help='Path to your iOS Simulator Debug out directory, if you are building Sky locally. '
                 'This path is relative to sky-src-path. Not normally required.',
            default='out/ios_sim_Debug/')

        subparsers = parser.add_subparsers(help='sub-command help')

        for command in [StartSky(), StopSky(), StartListening(), StartTracing(), StopTracing(), IOSSimulator()]:
            command.add_subparser(subparsers)

        args = parser.parse_args()
        if args.local_build and args.sky_src_path is None:
            real_sky_path = os.path.realpath(os.path.join(PACKAGES_DIR, 'sky'))
            match = re.match(r'pub.dartlang.org/sky', real_sky_path)
            if match is not None:
                args.local_build = False
            else:
                sky_src_path = os.path.dirname(
                    os.path.dirname(
                        os.path.dirname(
                            os.path.dirname(real_sky_path))))
                if sky_src_path == '/' or sky_src_path == '':
                    args.local_build = False
                else:
                    args.sky_src_path = sky_src_path

            if not args.local_build:
                logging.warning('Unable to detect a valid sky install. Disabling local-build flag.\n'
                                'The recommended way to use a local build of Sky is to add the following\n'
                                'to your pubspec.yaml file and then run pub get again:\n'
                                'dependency_overrides:\n'
                                '  material_design_icons:\n'
                                '    path: /path/to/sky_engine/src/sky/packages/material_design_icons\n'
                                '  sky:\n'
                                '    path: /path/to/sky_engine/src/sky/packages/sky\n')

        pids = Pids.read_from(PID_FILE_PATH, PID_FILE_KEYS)
        atexit.register(pids.write_to, PID_FILE_PATH)
        exit_code = 0
        try:
          exit_code = args.func(args, pids)
        except subprocess.CalledProcessError as e:
          # Don't print a stack trace if the adb command fails.
          logging.error(e)
          exit_code = 2
        sys.exit(exit_code)


if __name__ == '__main__':
    sys.exit(SkyShellRunner().main())
