#!/usr/bin/python
# Copyright 2015 The Chromium OS 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 sys

import logging
# Turn the logging level to INFO before importing other autotest
# code, to avoid having failed import logging messages confuse the
# test_droid user.
logging.basicConfig(level=logging.INFO)


import common
# Unfortunately, autotest depends on external packages for assorted
# functionality regardless of whether or not it is needed in a particular
# context.
# Since we can't depend on people to import these utilities in any principled
# way, we dynamically download code before any autotest imports.
try:
    import chromite.lib.terminal  # pylint: disable=unused-import
    import django.http  # pylint: disable=unused-import
except ImportError:
    # Ensure the chromite site-package is installed.
    import subprocess
    build_externals_path = os.path.join(
            os.path.dirname(os.path.dirname(os.path.realpath(__file__))),
            'utils', 'build_externals.py')
    subprocess.check_call([build_externals_path, 'chromiterepo', 'django'])
    # Restart the script so python now finds the autotest site-packages.
    sys.exit(os.execv(__file__, sys.argv))

from autotest_lib.client.common_lib import utils
from autotest_lib.server.hosts import adb_host
from autotest_lib.site_utils import test_runner_utils
from autotest_lib.site_utils import tester_feedback


def parse_arguments(argv):
    """
    Parse command line arguments

    @param argv: argument list to parse

    @returns:    parsed arguments

    @raises SystemExit if arguments are malformed, or required arguments
            are not present.
    """
    return _parse_arguments_internal(argv)[0]


def _parse_arguments_internal(argv):
    """
    Parse command line arguments

    @param argv: argument list to parse

    @returns:    tuple of parsed arguments and argv suitable for remote runs

    @raises SystemExit if arguments are malformed, or required arguments
            are not present.
    """

    parser = argparse.ArgumentParser(description='Run remote tests.')

    parser.add_argument('-s', '--serials', metavar='SERIALS',
                        help='Comma separate list of device serials under '
                             'test.')
    parser.add_argument('-f', '--fastboot_serial', metavar='FB_SERIALS',
                        help='Comma separate list of fastboot serials under '
                             'test.', default=None)
    parser.add_argument('-r', '--remote', metavar='REMOTE',
                        default='localhost',
                        help='hostname[:port] if the ADB device is connected '
                             'to a remote machine. Ensure this workstation '
                             'is configured for passwordless ssh access as '
                             'users "root" or "adb"')
    parser.add_argument('-i', '--interactive', action='store_true',
                        help='Enable interactive feedback requests from tests.')
    test_runner_utils.add_common_args(parser)
    return parser.parse_args(argv)


def main(argv):
    """
    Entry point for test_droid script.

    @param argv: arguments list
    """
    arguments = _parse_arguments_internal(argv)

    serials = arguments.serials
    if serials is None:
        result = utils.run(['adb', 'devices'])
        devices = adb_host.ADBHost.parse_device_serials(result.stdout)
        if len(devices) != 1:
            logging.error('could not detect exactly one device; please select '
                          'one with -s: %s', devices)
            return 1
        serials = devices[0]

    results_directory = test_runner_utils.create_results_directory(
            arguments.results_dir)
    arguments.results_dir = results_directory

    autotest_path = os.path.dirname(os.path.dirname(
            os.path.realpath(__file__)))
    site_utils_path = os.path.join(autotest_path, 'site_utils')
    realpath = os.path.realpath(__file__)
    site_utils_path = os.path.realpath(site_utils_path)
    host_attributes = {'serials' : serials,
                       'os_type' : 'android'}
    if arguments.fastboot_serial:
        host_attributes['fastboot_serial'] = arguments.fastboot_serial

    fb_service = None
    try:
        # Start the feedback service if needed.
        if arguments.interactive:
            fb_service = tester_feedback.FeedbackService()
            fb_service.start()

            if arguments.args:
                arguments.args += ' '
            else:
                arguments.args = ''
            arguments.args += (
                    'feedback=interactive feedback_args=localhost:%d' %
                    fb_service.server_port)

        return test_runner_utils.perform_run_from_autotest_root(
                    autotest_path, argv, arguments.tests, arguments.remote,
                    args=arguments.args, ignore_deps=not arguments.enforce_deps,
                    results_directory=results_directory,
                    iterations=arguments.iterations,
                    fast_mode=arguments.fast_mode, debug=arguments.debug,
                    host_attributes=host_attributes, pretend=arguments.pretend)
    finally:
        if fb_service is not None:
            fb_service.stop()


if __name__ == '__main__':
    sys.exit(main(sys.argv[1:]))
