# Copyright 2018 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.

"""Wrapper for running suites of tests and waiting for completion."""

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import os
import sys

import logging

from lucifer import autotest
from skylab_suite import cros_suite
from skylab_suite import suite_parser
from skylab_suite import suite_runner
from skylab_suite import suite_tracking
from skylab_suite import swarming_lib


PROVISION_SUITE_NAME = 'provision'


def _parse_suite_handler_spec(options):
    provision_num_required = 0
    if 'num_required' in options.suite_args:
        provision_num_required = options.suite_args['num_required']

    return cros_suite.SuiteHandlerSpec(
            suite_name=options.suite_name,
            wait=not options.create_and_return,
            suite_id=options.suite_id,
            timeout_mins=options.timeout_mins,
            passed_mins=options.passed_mins,
            test_retry=options.test_retry,
            max_retries=options.max_retries,
            provision_num_required=provision_num_required)


def _should_run(suite_spec):
    tags = {'build': suite_spec.test_source_build,
            'suite': suite_spec.suite_name}
    tasks = swarming_lib.query_task_by_tags(tags)
    current_task_id = suite_tracking.get_task_id_for_task_summaries(
            os.environ.get('SWARMING_TASK_ID'))
    logging.info('The current task id is: %s', current_task_id)
    extra_task_ids = set([])
    for t in tasks:
        if t['task_id'] != current_task_id:
            extra_task_ids.add(t['task_id'])

    return extra_task_ids


def _run_suite(options):
    run_suite_common = autotest.load('site_utils.run_suite_common')
    logging.info('Kicked off suite %s', options.suite_name)
    suite_spec = suite_parser.parse_suite_spec(options)
    if options.pre_check:
        extra_task_ids = _should_run(suite_spec)
        if extra_task_ids:
            logging.info(
                    'The same suites are already run in the past: \n%s',
                    '\n'.join([swarming_lib.get_task_link(tid)
                               for tid in extra_task_ids]))
            return run_suite_common.SuiteResult(
                    run_suite_common.RETURN_CODES.OK)

    if options.suite_name == PROVISION_SUITE_NAME:
        suite_job = cros_suite.ProvisionSuite(suite_spec)
    else:
        suite_job = cros_suite.Suite(suite_spec)

    try:
        suite_job.prepare()
    except Exception as e:
        logging.exception('Infra failure in setting up suite job')
        return run_suite_common.SuiteResult(
                run_suite_common.RETURN_CODES.INFRA_FAILURE)

    suite_handler_spec = _parse_suite_handler_spec(options)
    suite_handler = cros_suite.SuiteHandler(suite_handler_spec)
    suite_runner.run(suite_job.test_specs,
                     suite_handler,
                     options.dry_run)

    if options.create_and_return:
        suite_tracking.print_child_test_annotations(suite_handler)
        return run_suite_common.SuiteResult(run_suite_common.RETURN_CODES.OK)

    return_code = suite_tracking.log_suite_results(
                suite_job.suite_name, suite_handler)
    return run_suite_common.SuiteResult(return_code)


def parse_args():
    """Parse & validate skylab suite args."""
    parser = suite_parser.make_parser()
    options = parser.parse_args()
    if options.do_nothing:
        logging.info('Exit early because --do_nothing requested.')
        sys.exit(0)

    if not suite_parser.verify_and_clean_options(options):
        parser.print_help()
        sys.exit(1)

    return options


def main():
    """Entry point."""
    autotest.monkeypatch()

    options = parse_args()
    suite_tracking.setup_logging()
    result = _run_suite(options)
    logging.info('Will return from %s with status: %s',
                 os.path.basename(__file__), result.string_code)
    return result.return_code


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