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

"""This is a display hot-plug and suspend test using the Chameleon board."""

from __future__ import print_function

import logging
import time

from autotest_lib.client.bin import utils
from autotest_lib.client.common_lib import error
from autotest_lib.client.cros.chameleon import chameleon_port_finder
from autotest_lib.client.cros.chameleon import chameleon_screen_test
from autotest_lib.server import test
from autotest_lib.server.cros.multimedia import remote_facade_factory


class display_HotPlugAtSuspend(test.test):
    """Display hot-plug and suspend test.

    This test talks to a Chameleon board and a DUT to set up, run, and verify
    DUT behavior response to different configuration of hot-plug during
    suspend/resume.
    """
    version = 1
    # Duration of suspend, in second.
    SUSPEND_DURATION = 40
    # Allowed timeout for the transition of suspend.
    SUSPEND_TIMEOUT = 30
    # Allowed timeout for the transition of resume.
    RESUME_TIMEOUT = 60
    # Time margin to do plug/unplug before resume.
    TIME_MARGIN_BEFORE_RESUME = 5
    # Timeout of waiting DUT mirrored.
    TIMEOUT_WAITING_MIRRORED = 5


    def run_once(self, host, plug_status, test_mirrored=False):
        if test_mirrored and not host.get_board_type() == 'CHROMEBOOK':
            raise error.TestNAError('DUT is not Chromebook. Test Skipped')

        factory = remote_facade_factory.RemoteFacadeFactory(host)
        display_facade = factory.create_display_facade()
        chameleon_board = host.chameleon

        chameleon_board.setup_and_reset(self.outputdir)
        finder = chameleon_port_finder.ChameleonVideoInputFinder(
                chameleon_board, display_facade)

        errors = []
        is_display_failure = False
        for chameleon_port in finder.iterate_all_ports():
            screen_test = chameleon_screen_test.ChameleonScreenTest(
                    host, chameleon_port, display_facade, self.outputdir)

            logging.info('See the display on Chameleon: port %d (%s)',
                         chameleon_port.get_connector_id(),
                         chameleon_port.get_connector_type())

            logging.info('Set mirrored: %s', test_mirrored)
            display_facade.set_mirrored(test_mirrored)

            # Keep the original connector name, for later comparison.
            expected_connector = display_facade.get_external_connector_name()
            resolution = display_facade.get_external_resolution()
            logging.info('See the display on DUT: %s %r',
                         expected_connector, resolution)

            for (plugged_before_suspend, plugged_after_suspend,
                 plugged_before_resume) in plug_status:
                test_case = ('TEST CASE: %s > SUSPEND > %s > %s > RESUME' %
                    ('PLUG' if plugged_before_suspend else 'UNPLUG',
                     'PLUG' if plugged_after_suspend else 'UNPLUG',
                     'PLUG' if plugged_before_resume else 'UNPLUG'))
                logging.info(test_case)
                boot_id = host.get_boot_id()
                chameleon_port.set_plug(plugged_before_suspend)

                if screen_test.check_external_display_connected(
                        expected_connector if plugged_before_suspend else False,
                        errors):
                    is_display_failure = True
                    # Skip the following test if an unexpected display detected.
                    continue

                logging.info('GOING TO SUSPEND FOR %d SECONDS...',
                             self.SUSPEND_DURATION)
                time_before_suspend = time.time()
                display_facade.suspend_resume_bg(self.SUSPEND_DURATION)

                # Confirm DUT suspended.
                logging.info('WAITING FOR SUSPEND...')
                try:
                    host.test_wait_for_sleep(self.SUSPEND_TIMEOUT)
                except error.TestFail as ex:
                    errors.append("%s - %s" % (test_case, str(ex)))
                if plugged_after_suspend is not plugged_before_suspend:
                    chameleon_port.set_plug(plugged_after_suspend)

                current_time = time.time()
                sleep_time = (self.SUSPEND_DURATION -
                              (current_time - time_before_suspend) -
                              self.TIME_MARGIN_BEFORE_RESUME)
                if sleep_time > 0:
                    logging.info('- Sleep for %.2f seconds...', sleep_time)
                    time.sleep(sleep_time)
                if plugged_before_resume is not plugged_after_suspend:
                    chameleon_port.set_plug(plugged_before_resume)
                time.sleep(self.TIME_MARGIN_BEFORE_RESUME)

                logging.info('WAITING FOR RESUME...')
                try:
                    host.test_wait_for_resume(boot_id, self.RESUME_TIMEOUT)
                except error.TestFail as ex:
                    errors.append("%s - %s" % (test_case, str(ex)))

                logging.info('Resumed back')

                if screen_test.check_external_display_connected(
                        expected_connector if plugged_before_resume else False,
                        errors):
                    # Skip the following test if an unexpected display detected.
                    continue

                if plugged_before_resume:
                    if test_mirrored and (not utils.wait_for_value(
                            display_facade.is_mirrored_enabled, True,
                            timeout_sec=self.TIMEOUT_WAITING_MIRRORED)):
                        error_message = 'Error: not resumed to mirrored mode'
                        errors.append("%s - %s" % (test_case, error_message))
                        logging.error(error_message)
                        logging.info('Set mirrored: %s', True)
                        display_facade.set_mirrored(True)
                    elif screen_test.test_screen_with_image(
                                resolution, test_mirrored, errors):
                        is_display_failure = True

        if errors:
            if is_display_failure:
                raise error.TestFail('; '.join(set(errors)))
            else:
                raise error.TestError('; '.join(set(errors)))
