# Copyright 2018 The Fuchsia 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 os
import re
import shutil
from subprocess import Popen, PIPE
import sys
import tempfile


def run_command(*args, **kwargs):
    no_redirect = kwargs.pop('no_redirect', False)
    output = None if no_redirect else PIPE
    process = Popen(args, stdout=output, stderr=output)
    stdout, stderr = process.communicate()
    if process.returncode:
        if no_redirect:
            raise Exception('Command %s failed' % args)
        else:
            raise Exception('Command %s failed: %s' % (args, stdout + stderr))
    return stdout


def get_device_addresses(dev_finder):
    # Find a target device.
    stdout = run_command(dev_finder, 'list', '-device_limit', '1', '-full')
    match = re.match('^([^\s]+)\s+([^\s]+)$', stdout.strip())
    if not match:
        raise Exception('Could not parse target parameters in %s' % stdout)
    target_address = match.group(1)
    target_name = match.group(2)

    # Get the matching host address for that device.
    stdout = run_command(dev_finder, 'resolve', '-local', target_name)
    host_address = stdout.strip()
    return target_address, host_address


def serve_package(pm, package, directory):
    # Set up the package repository.
    run_command(pm, 'newrepo', '-repo', directory)
    run_command(pm, 'publish', '-a', '-r', directory, '-f', package)

    # Start the server.
    server = Popen([pm, 'serve', '-repo', directory+'/repository'], stdout=PIPE,
                   stderr=PIPE)
    return lambda: server.kill()


class MyParser(argparse.ArgumentParser):

    def error(self, message):
        print('Usage: bazel run <package label> -- <component name> --ssh-key '
              '<path to private key>')
        sys.exit(1)


def main():
    parser = MyParser()
    parser.add_argument('--config',
                        help='The path to the list of components in the package',
                        required=True)
    parser.add_argument('--package-name',
                        help='The name of the Fuchsia package',
                        required=True)
    parser.add_argument('--package',
                        help='The path to the Fuchsia package',
                        required=True)
    parser.add_argument('--dev-finder',
                        help='The path to the dev_finder tool',
                        required=True)
    parser.add_argument('--pm',
                        help='The path to the pm tool',
                        required=True)
    subparse = parser.add_subparsers().add_parser('run')
    subparse.add_argument('component',
                          nargs=1)
    subparse.add_argument('--ssh-key',
                          help='The absolute path to a private SSH key',
                          required=True)
    args = parser.parse_args()

    if not os.path.isabs(args.ssh_key):
        print('Path to SSH key must be absolute, got %s' % args.ssh_key)
        return 1

    with open(args.config, 'r') as config_file:
        components = config_file.readlines()

    component = args.component[0]
    if component not in components:
        print('Error: "%s" not in %s' % (component, components))
        return 1

    staging_dir = tempfile.mkdtemp(prefix='fuchsia-run')

    try:
        target_address, host_address = get_device_addresses(args.dev_finder)
        stop_server = serve_package(args.pm, args.package, staging_dir)
        try:
            def run_ssh_command(*params, **kwargs):
                base = [
                    'ssh', '-i', args.ssh_key,
                    'fuchsia@' + target_address,
                    '-o', 'StrictHostKeyChecking=no',
                    '-o', 'UserKnownHostsFile=/dev/null',
                ]
                run_command(*(base + list(params)), **kwargs)
            server_address = 'http://%s:8083/config.json' % host_address
            run_ssh_command('amber_ctl', 'add_src', '-x', '-f', server_address)
            component_uri = "fuchsia-pkg://fuchsia.com/%s#meta/%s.cmx" % (
                    args.package_name, component)
            run_ssh_command('run', component_uri, no_redirect=True)
        finally:
            stop_server()
    except Exception as e:
        print(e)
        return 1
    finally:
        shutil.rmtree(staging_dir, ignore_errors=True)

    return 0


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