#!/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.

import skypy.paths
from skypy.skyserver import SkyServer
import argparse
import json
import logging
import os
import pipes
import requests
import signal
import subprocess
import sys
import time
import urlparse

SRC_ROOT = skypy.paths.Paths('ignored').src_root
sys.path.insert(0, os.path.join(SRC_ROOT, 'build', 'android'))
from pylib import android_commands
from pylib import constants
from pylib import forwarder


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

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


# 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):
        build_dir_url = SkyServer.url_for_path(
            self.pids['remote_sky_server_port'],
            self.pids['sky_server_root'],
            self.pids['build_dir'])
        shell_args += ['--origin=%s' % build_dir_url]

        # 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', 'shell',
            'am', 'start',
            '-W',
            '-S',
            '-a', 'android.intent.action.VIEW',
            '-n', 'org.chromium.mojo.shell/.MojoShellActivity',
            # 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):
        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'])

        shell_args = [
            '--v=1',
            '--content-handlers=%s' % ','.join(content_handlers),
            '--url-mappings=mojo:window_manager=mojo:sky_debugger',
            '--args-for=mojo:sky_debugger_prompt %d' % remote_command_port,
            'mojo:window_manager',
        ]
        # FIXME: This probably is wrong for android?
        if args.use_osmesa:
            shell_args.append('--args-for=mojo:native_viewport_service --use-osmesa')

        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 _connect_to_device(self):
        device = android_commands.AndroidCommands(
            android_commands.GetAttachedDevices()[0])
        device.EnableAdbRoot()
        return device

    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(args.build_dir))
        server_root = self._server_root_for_url(args.url_or_path)
        sky_server = SkyServer(self.paths, 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 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.
        self.pids = {} # Clear out our pid file.

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

        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'] = args.build_dir
        self.pids['sky_command_port'] = args.command_port

        if is_android:
            # Pray to the build/android gods in their misspelled tongue.
            constants.SetOutputDirectort(args.build_dir)

            device = self._connect_to_device()
            self.pids['device_serial'] = device.GetDevice()

            forwarder.Forwarder.Map([(0, sky_server.port)], device)
            device_http_port = forwarder.Forwarder.DevicePortForHostPort(
                sky_server.port)
            self.pids['remote_sky_server_port'] = device_http_port

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

        shell_command = self._build_mojo_shell_command(args)

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

        print ' '.join(map(pipes.quote, shell_command))
        self.pids['mojo_shell_pid'] = subprocess.Popen(shell_command).pid

        if args.gdb and is_android:
            gdbserver_cmd = ['gdbserver', '--attach', ':%s' % GDB_PORT]
            self.pids['remote_gdbserver_pid'] = subprocess.Popen(shell_command).pid

            port_string = 'tcp:%s' % GDB_PORT
            subprocess.check_call([
                'adb', '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:
                self.load_command(args)
        else:
            print 'No load issued, connect with gdb first and then run load.'

    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 (%s).' % (name, pid))
        try:
            os.kill(pid, signal.SIGTERM)
        except OSError:
            logging.info('%s (%s) already gone.' % (name, pid))

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

        self._kill_if_exists('sky_server_pid', 'sky_server')
        # We could be much more surgical here:
        if 'remote_sky_server_port' in self.pids:
            device = android_commands.AndroidCommands(
                self.pids['device_serial'])
            forwarder.Forwarder.UnmapAllDevicePorts(device)

        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', 'forward', '--remove', port_string])

        if 'remote_gdbserver_port' in self.pids:
            port_string = 'tcp:%s' % self.pids['remote_gdbserver_port']
            subprocess.call(['adb', 'forward', '--remove', port_string])

    def load_command(self, args):
        if not urlparse.urlparse(args.url_or_path).scheme:
            # 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'])
            url = SkyServer.url_for_path(remote_sky_server_port,
                    self.pids['sky_server_root'], args.url_or_path)
        else:
            url = args.url_or_path
        self._send_command_to_sky('/load', url)

    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)
        print response.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._send_command_to_sky(url_path)
        parser.set_defaults(func=command)

    def _wait_for_sky_command_port(self):
        tries = 0
        while True:
            try:
                self._send_command_to_sky('/')
                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', 'logcat', '-s'] + TAGS)

    def gdb_attach_command(self, args):
        self.paths = self._create_paths_for_build_dir(self.pids['build_dir'])
        gdb_command = [
            '/usr/bin/gdb', self.paths.mojo_shell_path,
            '--eval-command', 'target remote localhost:%s' % GDB_PORT
        ]
        print " ".join(gdb_command)
        # We don't want python listenting for signals or anything, so exec
        # gdb and let it take the entire process.
        os.execv(gdb_command[0], gdb_command)

    def main(self):
        logging.basicConfig(level=logging.INFO)
        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)

        logcat_parser = subparsers.add_parser('logcat',
            help=('dump sky-related logs from device'))
        logcat_parser.set_defaults(func=self.logcat_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, 'trace', '/trace',
            'toggle tracing')
        self._add_basic_command(subparsers, 'reload', '/reload',
            'reload the current page')
        self._add_basic_command(subparsers, 'inspect', '/inspect',
            'stop the running sky instance')

        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()
