#!/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.paths import Paths
from skypy.skyserver import SkyServer
import argparse
import json
import logging
import os
import requests
import signal
import skypy.configuration as configuration
import subprocess
import urlparse
import time


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

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


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

    def _server_root_for_url(self, url_or_path):
        path = os.path.abspath(url_or_path)
        if os.path.commonprefix([path, self.paths.src_root]) == self.paths.src_root:
            server_root = self.paths.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 _build_mojo_shell_command(self, args):
        self.paths = Paths(os.path.join('out', args.configuration))

        content_handlers = ['%s,%s' % (mime_type, 'mojo:sky_viewer')
            for mime_type in SUPPORTED_MIME_TYPES]
        shell_command = [
            self.paths.mojo_shell_path,
            '--v=1',
            '--content-handlers=%s' % ','.join(content_handlers),
            '--url-mappings=mojo:window_manager=mojo:sky_debugger',
            '--args-for=mojo:sky_debugger_prompt %d' % args.command_port,
            'mojo:window_manager',
        ]
        if args.use_osmesa:
            shell_command.append('--args-for=mojo:native_viewport_service --use-osmesa')

        if args.gdb:
            shell_command = ['gdb', '--args'] + shell_command

        return shell_command

    def start_command(self, args):
        shell_command = self._build_mojo_shell_command(args)
        if args.show_command:
            print " ".join(shell_command)
            return

        self.stop_command(None) # Quit any existing process.

        print args.url_or_path
        # We only start a server for paths:
        if not urlparse.urlparse(args.url_or_path).scheme:
            server_root = self._server_root_for_url(args.url_or_path)
            sky_server = SkyServer(self.paths, SKY_SERVER_PORT,
                args.configuration, server_root)
            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['mojo_shell_pid'] = subprocess.Popen(shell_command).pid
        self.pids['sky_command_port'] = args.command_port

        if not self._wait_for_sky_command_port():
            logging.error('Failed to start sky')
            self.stop_command(None)
        else:
            self.load_command(args)

    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):
        # FIXME: Send /quit to sky prompt instead of killing.
        # self._send_command_to_sky('/quit')
        self._kill_if_exists('mojo_shell_pid', 'mojo_shell')
        self._kill_if_exists('sky_server_pid', 'sky_server')

    def load_command(self, args):
        if not urlparse.urlparse(args.url_or_path).scheme:
            url = SkyServer.url_for_path(self.pids['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)
        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 main(self):
        logging.basicConfig(level=logging.INFO)

        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')
        configuration.add_arguments(start_parser)
        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('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)

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