#!/usr/bin/env python
# Copyright 2014 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 skypy.skyserver import SkyServer
import argparse
import json
import logging
import os
import pipes
import re
import requests
import signal
import skypy.paths
import StringIO
import subprocess
import sys
import time
import urlparse

SUPPORTED_MIME_TYPES = [
    'text/html',
    'text/sky',
    'text/plain',
]

DEFAULT_SKY_COMMAND_PORT = 7777
GDB_PORT = 8888
SKY_SERVER_PORT = 9999
DEFAULT_URL = "https://raw.githubusercontent.com/domokit/mojo/master/sky/examples/home.sky"

ANDROID_PACKAGE = "org.chromium.mojo.shell"
ANDROID_ACTIVITY = "%s/.MojoShellActivity" % ANDROID_PACKAGE
ANDROID_APK_NAME = 'MojoShell.apk'

PID_FILE_PATH = "/tmp/skydb.pids"
CACHE_LINKS_PATH = '/tmp/mojo_cache_links'
SYSTEM_LIBS_ROOT_PATH = '/tmp/device_libs'

SRC_ROOT = skypy.paths.Paths('ignored').src_root
ADB_PATH = os.path.join(SRC_ROOT,
    'third_party/android_tools/sdk/platform-tools/adb')


# FIXME: Move this into mopy.config
def gn_args_from_build_dir(build_dir):
    gn_cmd = [
        'gn', 'args',
        build_dir,
        '--list', '--short'
    ]
    config = {}
    for line in subprocess.check_output(gn_cmd).strip().split('\n'):
        # FIXME: This doesn't handle = in values.
        key, value = line.split(' = ')
        config[key] = value
    return config


class SkyDebugger(object):
    def __init__(self):
        self.pids = {}
        self.paths = None

    def _server_root_for_url(self, url_or_path):
        path = os.path.abspath(url_or_path)
        if os.path.commonprefix([path, SRC_ROOT]) == SRC_ROOT:
            server_root = SRC_ROOT
        else:
            server_root = os.path.dirname(path)
            logging.warn(
                '%s is outside of mojo root, using %s as server root' %
                (path, server_root))
        return server_root

    def _in_chromoting(self):
        return os.environ.get('CHROME_REMOTE_DESKTOP_SESSION', False)

    def _wrap_for_android(self, shell_args):
        # am shell --esa: (someone shoot me now)
        #  [--esa <EXTRA_KEY> <EXTRA_STRING_VALUE>[,<EXTRA_STRING_VALUE...]]
        #  (to embed a comma into a string escape it using "\,")
        escaped_args = map(lambda arg: arg.replace(',', '\\,'), shell_args)
        return [
            ADB_PATH, 'shell',
            'am', 'start',
            '-W',
            '-S',
            '-a', 'android.intent.action.VIEW',
            '-n', ANDROID_ACTIVITY,
            # FIXME: This quoting is very error-prone.  Perhaps we should read
            # our args from a file instead?
            '--esa', 'parameters', ','.join(escaped_args),
        ]

    def _build_mojo_shell_command(self, args, is_android):
        content_handlers = ['%s,%s' % (mime_type, 'mojo:sky_viewer')
            for mime_type in SUPPORTED_MIME_TYPES]

        remote_command_port = self.pids.get('remote_sky_command_port', self.pids['sky_command_port'])
        remote_server_port = self.pids.get('remote_sky_server_port', self.pids['sky_server_port'])

        shell_args = [
            '--v=1',
            '--content-handlers=%s' % ','.join(content_handlers),
            '--url-mappings=mojo:window_manager=mojo:kiosk_wm',
            '--args-for=mojo:sky_debugger %d' % remote_command_port,
            'mojo:sky_debugger',
        ]

        if args.url_or_path:
            shell_args.append(
                '--args-for=mojo:window_manager %s' % self._url_from_args(args))

        # Map all mojo: urls to http: urls using the --origin command.
        build_dir_url = SkyServer.url_for_path(
            remote_server_port,
            self.pids['sky_server_root'],
            self.pids['build_dir'])

        # TODO(eseidel): We should do this on linux, but we need to fix
        # mojo http loading to be faster first.
        if is_android:
            shell_args += ['--origin=%s' % build_dir_url]

        # Desktop-only work-around for mojo crashing under chromoting.
        if not is_android and args.use_osmesa:
            shell_args.append(
                '--args-for=mojo:native_viewport_service --use-osmesa')

        if is_android and args.gdb:
            shell_args.append('--wait-for-debugger')

        if 'remote_sky_server_port' in self.pids:
            shell_command = self._wrap_for_android(shell_args)
        else:
            shell_command = [self.paths.mojo_shell_path] + shell_args

        return shell_command

    def sky_server_for_args(self, args):
        # FIXME: This is a hack.  sky_server should just take a build_dir
        # not a magical "configuration" name.
        configuration = os.path.basename(os.path.normpath(self.paths.build_dir))
        server_root = self._server_root_for_url(args.url_or_path)
        sky_server = SkyServer(SKY_SERVER_PORT, configuration, server_root)
        return sky_server

    def _create_paths_for_build_dir(self, build_dir):
        # skypy.paths.Paths takes a root-relative build_dir argument. :(
        abs_build_dir = os.path.abspath(build_dir)
        root_relative_build_dir = os.path.relpath(abs_build_dir, SRC_ROOT)
        return skypy.paths.Paths(root_relative_build_dir)

    def _find_remote_pid_for_package(self, package):
        ps_output = subprocess.check_output([ADB_PATH, 'shell', 'ps'])
        for line in ps_output.split('\n'):
            fields = line.split()
            if fields and fields[-1] == package:
                return fields[1]
        return None

    def _find_install_location_for_package(self, package):
        pm_command = [ADB_PATH, 'shell', 'pm', 'path', package]
        pm_output = subprocess.check_output(pm_command)
        # e.g. package:/data/app/org.chromium.mojo.shell-1/base.apk
        return pm_output.split(':')[-1]

    def start_command(self, args):
        # FIXME: Lame that we use self for a command-specific variable.
        self.paths = self._create_paths_for_build_dir(args.build_dir)
        self.stop_command(None) # Quit any existing process.

        if not os.path.exists(self.paths.mojo_shell_path):
            print "mojo_shell not found in build_dir '%s'" % args.build_dir
            print "Are you sure you sure that's a valid build_dir location?"
            print "See skydb start --help for more info"
            sys.exit(2)

        # FIXME: This is probably not the right way to compute is_android
        # from the build directory?
        gn_args = gn_args_from_build_dir(self.paths.build_dir)
        is_android = 'android_sdk_version' in gn_args

        if is_android and args.gdb and not 'is_debug' in gn_args:
            # FIXME: We don't include gdbserver in the release APK...
            print "Cannot debug Release builds on Android"
            sys.exit(2)

        sky_server = self.sky_server_for_args(args)
        self.pids['sky_server_pid'] = sky_server.start()
        self.pids['sky_server_port'] = sky_server.port
        self.pids['sky_server_root'] = sky_server.root

        self.pids['build_dir'] = self.paths.build_dir
        self.pids['sky_command_port'] = args.command_port

        if is_android:
            # TODO(eseidel): This should move into a helper method and handle
            # failures with nice messages explaining how to get root.
            subprocess.check_call([ADB_PATH, 'root'])

            # We could make installing conditional on an argument.
            apk_path = os.path.join(self.paths.build_dir, 'apks',
                ANDROID_APK_NAME)
            subprocess.check_call([ADB_PATH, 'install', '-r', apk_path])

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

            port_string = 'tcp:%s' % args.command_port
            subprocess.check_call([
                ADB_PATH, 'forward', port_string, port_string
            ])
            self.pids['remote_sky_command_port'] = args.command_port

        shell_command = self._build_mojo_shell_command(args, is_android)

        # On android we can't launch inside gdb, but rather have to attach.
        if not is_android and args.gdb:
            shell_command = ['gdbserver', ':%d' % GDB_PORT] + shell_command

        print ' '.join(map(pipes.quote, shell_command))
        # This pid is meaningless on android (it's the adb shell pid)
        start_command_pid = subprocess.Popen(shell_command).pid

        if is_android:
            # TODO(eseidel): am start -W does not seem to work?
            pid_tries = 0
            while True:
                pid = self._find_remote_pid_for_package(ANDROID_PACKAGE)
                if pid or pid_tries > 3:
                    break
                logging.debug('No pid for %s yet, waiting' % ANDROID_PACKAGE)
                time.sleep(5)
                pid_tries += 1

            if not pid:
                logging.error('Failed to find mojo_shell pid on device!')
                return
            self.pids['mojo_shell_pid'] = pid
        else:
            self.pids['mojo_shell_pid'] = start_command_pid

        if args.gdb and is_android:
            # We push our own copy of gdbserver with the package since
            # the default gdbserver is a different version from our gdb.
            package_path = \
                self._find_install_location_for_package(ANDROID_PACKAGE)
            gdb_server_path = os.path.join(
                os.path.dirname(package_path), 'lib/arm/gdbserver')
            gdbserver_cmd = [
                ADB_PATH, 'shell',
                gdb_server_path, '--attach',
                ':%d' % GDB_PORT,
                str(self.pids['mojo_shell_pid'])
            ]
            print ' '.join(map(pipes.quote, gdbserver_cmd))
            self.pids['adb_shell_gdbserver_pid'] = \
                subprocess.Popen(gdbserver_cmd).pid

            port_string = 'tcp:%d' % GDB_PORT
            subprocess.check_call([
                ADB_PATH, 'forward', port_string, port_string
            ])
            self.pids['remote_gdbserver_port'] = GDB_PORT

        if not args.gdb:
            if not self._wait_for_sky_command_port():
                logging.error('Failed to start sky')
                self.stop_command(None)
        else:
            # We could just run gdb_attach_command here, but when I do that
            # it auto-suspends in my zsh.  Unclear why.
            # self.gdb_attach_command(args)
            print "Run 'skydb gdb_attach' to attach."

    def _kill_if_exists(self, key, name):
        pid = self.pids.pop(key, None)
        if not pid:
            logging.info('No pid for %s, nothing to do.' % name)
            return
        logging.info('Killing %s (%d).' % (name, pid))
        try:
            os.kill(pid, signal.SIGTERM)
        except OSError:
            logging.info('%s (%d) already gone.' % (name, pid))

    def stop_command(self, args):
        # TODO(eseidel): mojo_shell crashes when attempting graceful shutdown.
        # self._run_basic_command('/quit')

        self._kill_if_exists('sky_server_pid', 'sky_server')

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

        if 'remote_sky_command_port' in self.pids:
            # adb forward --remove takes the *host* port, not the remote port.
            port_string = 'tcp:%s' % self.pids['sky_command_port']
            subprocess.call([ADB_PATH, 'forward', '--remove', port_string])

            subprocess.call([
                ADB_PATH, 'shell', 'am', 'force-stop', ANDROID_PACKAGE])
        else:
            # Only try to kill mojo_shell if it's running locally.
            self._kill_if_exists('mojo_shell_pid', 'mojo_shell')

        if 'remote_gdbserver_port' in self.pids:
            self._kill_if_exists('adb_shell_gdbserver_pid',
                'adb shell gdbserver')

            port_string = 'tcp:%s' % self.pids['remote_gdbserver_port']
            subprocess.call([ADB_PATH, 'forward', '--remove', port_string])
        self.pids = {} # Clear out our pid file.

    def _url_from_args(self, args):
        if urlparse.urlparse(args.url_or_path).scheme:
            return args.url_or_path
        # The load happens on the remote device, use the remote port.
        remote_sky_server_port = self.pids.get('remote_sky_server_port',
            self.pids['sky_server_port'])
        return SkyServer.url_for_path(remote_sky_server_port,
            self.pids['sky_server_root'], args.url_or_path)

    def load_command(self, args):
        self._run_basic_command('/load', self._url_from_args(args))

    def _read_mojo_map(self):
        # TODO(eseidel): Does not work for android.
        mojo_map_path = "/tmp/mojo_shell.%d.maps" % self.pids['mojo_shell_pid']
        with open(mojo_map_path, 'r') as maps_file:
            lines = maps_file.read().strip().split('\n')
            return dict(map(lambda line: line.split(' '), lines))

    def stop_tracing_command(self, args):
        file_name = args.file_name
        trace = self._send_command_to_sky('/stop_tracing').content
        with open(file_name, "wb") as trace_file:
            trace_file.write(trace)
        print "Trace saved in %s" % file_name

    def stop_profiling_command(self, args):
        self._run_basic_command('/stop_profiling')
        mojo_map = self._read_mojo_map()

        # TODO(eseidel): We should have a helper for resolving urls, etc.
        remote_server_port = self.pids.get('remote_sky_server_port', self.pids['sky_server_port'])
        build_dir_url = SkyServer.url_for_path(
            remote_server_port,
            self.pids['sky_server_root'],
            self.pids['build_dir'])

        # Map /tmp cache paths to urls and then to local build_dir paths.
        def map_to_local_paths(match):
            path = match.group('mojo_path')
            url = mojo_map.get(path)
            if url and url.startswith(build_dir_url):
                return url.replace(build_dir_url, self.pids['build_dir'])
            return match.group(0)

        MOJO_PATH_RE = re.compile(r'(?P<mojo_path>\S+\.mojo)')
        MOJO_NAME_RE = re.compile(r'(?P<mojo_name>\w+)\.mojo')

        with open("sky_viewer.pprof", "rb+") as profile_file:
            # ISO-8859-1 can represent arbitrary binary while still keeping
            # ASCII characters in the ASCII range (allowing us to regexp).
            # http://en.wikipedia.org/wiki/ISO/IEC_8859-1
            as_string = profile_file.read().decode('iso-8859-1')
            # Using the mojo_shell.PID.maps file tmp paths to build_dir paths.
            as_string = MOJO_PATH_RE.sub(map_to_local_paths, as_string)
            # In release foo.mojo is stripped but libfoo_library.so isn't.
            as_string = MOJO_NAME_RE.sub(r'lib\1_library.so', as_string)
            profile_file.seek(0)
            profile_file.write(as_string.encode('iso-8859-1'))
            profile_file.truncate()

    def _command_base_url(self):
        return 'http://localhost:%s' % self.pids['sky_command_port']

    def _send_command_to_sky(self, command_path, payload=None):
        url = 'http://localhost:%s%s' % (
            self.pids['sky_command_port'], command_path)
        if payload:
            response = requests.post(url, payload)
        else:
            response = requests.get(url)
        return response

    def _run_basic_command(self, command_path, payload=None):
        print self._send_command_to_sky(command_path, payload=payload).text

    # FIXME: These could be made into a context object with __enter__/__exit__.
    def _load_pid_file(self, path):
        try:
            with open(path, 'r') as pid_file:
                return json.load(pid_file)
        except:
            if os.path.exists(path):
                logging.warn('Failed to read pid file: %s' % path)
            return {}

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

    def _add_basic_command(self, subparsers, name, url_path, help_text):
        parser = subparsers.add_parser(name, help=help_text)
        command = lambda args: self._run_basic_command(url_path)
        parser.set_defaults(func=command)

    def _wait_for_sky_command_port(self):
        tries = 0
        while True:
            try:
                self._run_basic_command('/')
                return True
            except:
                tries += 1
                if tries == 3:
                    logging.warn('Still waiting for sky on port %s' %
                        self.pids['sky_command_port'])
                if tries > 10:
                    return False
                time.sleep(1)

    def logcat_command(self, args):
        TAGS = [
            'AndroidHandler',
            'MojoMain',
            'MojoShellActivity',
            'MojoShellApplication',
            'chromium',
        ]
        subprocess.call([ADB_PATH, 'logcat', '-d', '-s'] + TAGS)

    def _pull_system_libraries(self, system_libs_root):
        # Pull down the system libraries this pid has already mapped in.
        # TODO(eseidel): This does not handle dynamic loads.
        library_cacher_path = os.path.join(
            self.paths.sky_tools_directory, 'android_library_cacher.py')
        subprocess.call([
            library_cacher_path, system_libs_root, self.pids['mojo_shell_pid']
        ])

        # TODO(eseidel): adb_gdb does, this, unclear why solib-absolute-prefix
        # doesn't make this explicit listing not necessary?
        return subprocess.check_output([
            'find', system_libs_root,
            '-mindepth', '1',
            '-maxdepth', '4',
            '-type', 'd',
        ]).strip().split('\n')

    def _add_android_library_links(self, links_path):
        # TODO(eseidel): This might not match mojo_shell on the device?
        # TODO(eseidel): Should we pass libmojo_shell.so as 'file' to gdb?
        shell_link_path = os.path.join(links_path, 'libmojo_shell.so')
        if os.path.lexists(shell_link_path):
            os.unlink(shell_link_path)
        os.symlink(self.paths.mojo_shell_path, shell_link_path)

    def gdb_attach_command(self, args):
        self.paths = self._create_paths_for_build_dir(self.pids['build_dir'])

        if not os.path.exists(CACHE_LINKS_PATH):
            os.makedirs(CACHE_LINKS_PATH)
        cache_linker_path = os.path.join(
             self.paths.sky_tools_directory, 'mojo_cache_linker.py')
        subprocess.check_call([
            cache_linker_path, CACHE_LINKS_PATH, self.paths.build_dir])

        symbol_search_paths = [
            self.pids['build_dir'],
            CACHE_LINKS_PATH,
        ]
        gdb_path = '/usr/bin/gdb'

        eval_commands = [
            'directory %s' % self.paths.src_root,
            'file %s' % self.paths.mojo_shell_path,
            'target remote localhost:%s' % GDB_PORT,
        ]

        # A bunch of extra work is needed for android:
        if 'remote_sky_server_port' in self.pids:
            self._add_android_library_links(CACHE_LINKS_PATH)

            system_lib_dirs = self._pull_system_libraries(SYSTEM_LIBS_ROOT_PATH)
            eval_commands.append(
                'set solib-absolute-prefix %s' % SYSTEM_LIBS_ROOT_PATH)

            symbol_search_paths = system_lib_dirs + symbol_search_paths

            # TODO(eseidel): We need to look up the toolchain somehow?
            gdb_path = os.path.join(SRC_ROOT, 'third_party/android_tools/ndk/'
                'toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/'
                'bin/arm-linux-androideabi-gdb')

        # Set solib-search-path after letting android modify symbol_search_paths
        eval_commands.append(
            'set solib-search-path %s' % ':'.join(symbol_search_paths))

        exec_command = [gdb_path]
        for command in eval_commands:
            exec_command += ['--eval-command', command]

        print " ".join(exec_command)

        # Write out our pid file before we exec ourselves.
        self._write_pid_file(PID_FILE_PATH, self.pids)

        # Exec gdb directly to avoid python intercepting symbols, etc.
        os.execv(exec_command[0], exec_command)

    def print_crash_command(self, args):
        logcat_cmd = [ADB_PATH, 'logcat', '-d']
        logcat = subprocess.Popen(logcat_cmd, stdout=subprocess.PIPE)

        stack_path = os.path.join(SRC_ROOT,
            'tools', 'android_stack_parser', 'stack')
        stack = subprocess.Popen([stack_path, '-'], stdin=logcat.stdout)
        logcat.wait()
        stack.wait()

    def pids_command(self, args):
        print json.dumps(self.pids, indent=1)

    def main(self):
        logging.basicConfig(level=logging.WARNING)
        logging.getLogger("requests").setLevel(logging.WARNING)

        self.pids = self._load_pid_file(PID_FILE_PATH)

        parser = argparse.ArgumentParser(description='Sky launcher/debugger')
        subparsers = parser.add_subparsers(help='sub-command help')

        start_parser = subparsers.add_parser('start',
            help='launch a new mojo_shell with sky')
        start_parser.add_argument('--gdb', action='store_true')
        start_parser.add_argument('--command-port', type=int,
            default=DEFAULT_SKY_COMMAND_PORT)
        start_parser.add_argument('--use-osmesa', action='store_true',
            default=self._in_chromoting())
        start_parser.add_argument('build_dir', type=str)
        start_parser.add_argument('url_or_path', nargs='?', type=str,
            default=DEFAULT_URL)
        start_parser.add_argument('--show-command', action='store_true',
            help='Display the shell command and exit')
        start_parser.set_defaults(func=self.start_command)

        stop_parser = subparsers.add_parser('stop',
            help=('stop sky (as listed in %s)' % PID_FILE_PATH))
        stop_parser.set_defaults(func=self.stop_command)

        pids_parser = subparsers.add_parser('pids',
            help='dump the current skydb pids file')
        pids_parser.set_defaults(func=self.pids_command)

        logcat_parser = subparsers.add_parser('logcat',
            help=('dump sky-related logs from device'))
        logcat_parser.set_defaults(func=self.logcat_command)

        print_crash_parser = subparsers.add_parser('print_crash',
            help=('dump (and symbolicate) recent crash-stacks'))
        print_crash_parser.set_defaults(func=self.print_crash_command)

        gdb_attach_parser = subparsers.add_parser('gdb_attach',
            help='launch gdb and attach to gdbserver launched from start --gdb')
        gdb_attach_parser.set_defaults(func=self.gdb_attach_command)

        self._add_basic_command(subparsers, 'start_tracing', '/start_tracing',
            'starts tracing the running sky instance')
        self._add_basic_command(subparsers, 'reload', '/reload',
            'reload the current page')
        self._add_basic_command(subparsers, 'start_profiling', '/start_profiling',
            'starts profiling the running sky instance (Linux only)')

        stop_tracing_parser = subparsers.add_parser('stop_tracing',
            help='stops tracing the running sky instance')
        stop_tracing_parser.add_argument('file_name', type=str, default='sky_viewer.trace')
        stop_tracing_parser.set_defaults(func=self.stop_tracing_command)

        stop_profiling_parser = subparsers.add_parser('stop_profiling',
            help='stops profiling the running sky instance (Linux only)')
        stop_profiling_parser.set_defaults(func=self.stop_profiling_command)

        load_parser = subparsers.add_parser('load',
            help='load a new page in the currently running sky')
        load_parser.add_argument('url_or_path', type=str)
        load_parser.set_defaults(func=self.load_command)

        args = parser.parse_args()
        args.func(args)

        self._write_pid_file(PID_FILE_PATH, self.pids)


if __name__ == '__main__':
    SkyDebugger().main()
