# Lint as: python2, python3
# Copyright 2014 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""This is test switching the external display mode."""

import logging, time

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_SwitchMode(test.test):
    """External Display switch between extended and mirrored modes.

    This test switches the external display mode between extended
    and mirrored modes, and checks resolution and static test image.
    """
    version = 1
    WAIT_AFTER_SWITCH = 5

    def check_external_display(self, test_mirrored):
        """Display status check

        @param test_mirrored: is mirrored mode active

        """
        resolution = self.display_facade.get_external_resolution()
        # Check connector
        if self.screen_test.check_external_display_connected(
                self.connector_used, self.errors) is None:
            # Check test image
            self.screen_test.test_screen_with_image(
                    resolution, test_mirrored, self.errors)
        if self.errors:
            raise error.TestFail('; '.join(set(self.errors)))


    def set_mode_and_check(self, test_mirrored, no_check):
        """Sets display mode and checks status

        @param test_mirrored: is mirrored mode active
        @param no_check: True to skip the screen check.
        """
        logging.info('Set mirrored: %s', test_mirrored)
        self.display_facade.set_mirrored(test_mirrored)
        if not no_check:
            time.sleep(self.WAIT_AFTER_SWITCH)
            self.check_external_display(test_mirrored)


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

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

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

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

            logging.debug('See the display on Chameleon: port %d (%s)',
                         self.chameleon_port.get_connector_id(),
                         self.chameleon_port.get_connector_type())
            # Keep the original connector name, for later comparison.
            self.connector_used = (
                    self.display_facade.get_external_connector_name())

            for i in range(repeat):
                logging.info("Iteration %d", (i + 1))
                self.set_mode_and_check(True, no_check)
                self.set_mode_and_check(False, no_check)
