# 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 end-to-end test using the Chameleon board."""

import logging, os, shutil, 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.client.cros.chameleon import edid
from autotest_lib.server import test
from autotest_lib.server.cros.multimedia import remote_facade_factory


class display_EndToEnd(test.test):
    """External Display end-toend test.

    This test talks to a Chameleon board and a DUT to set up, run, and verify
    DUT behavior response to reboot, login, docked mode, suspend and resume,
    switching mode, etc.
    """
    version = 1

    # Duration of suspend, in second.
    SUSPEND_DURATION = 30
    # Allowed timeout for the transition of suspend.
    SUSPEND_TIMEOUT = 30
    # Allowed timeout for the transition of resume.
    RESUME_TIMEOUT = 30
    # Allowed timeout for reboot.
    REBOOT_TIMEOUT = 60
    # Default waiting time in sec
    WAIT_TIME = 5
    # Crash paths to check for crash meta data
    CRASH_PATHS = ['/var/spool/crash',
                   '/chronos/home/crash'
                   '/home/chronos/user/crash'
                  ]
    # EDID data files names for different ports
    EDID_FILE_NAMES = [('DELL_U3011T_HDMI.txt', 'ASUS_VE258_HDMI.txt'),
                       ('MEL_18546_MDT551S_DP.txt', 'ASUS_VE258_DP.txt')]
    NO_LID_BOARDS = ['stumpy', 'panther', 'zako', 'tricky', 'mccloud']

    def remove_crash_data(self):
        """delete crash meta files"""
        for crash_path in self.CRASH_PATHS:
            if os.path.isdir(crash_path):
                shutil.rmtree(crash_path)


    def is_crash_data_present(self):
        """Check for crash meta files"""
        for crash_path in self.CRASH_PATHS:
            if os.path.isdir(crash_path):
                logging.debug('CRASH detected!')
                return True
        return False


    def switch_display_mode(self):
        """Switch from extended to mirror and the opposite"""
        from_mode = 'MIRRORED' if self.test_mirrored else 'EXTENDED'
        self.test_mirrored = not self.test_mirrored
        to_mode = 'MIRRORED' if self.test_mirrored else 'EXTENDED'
        logging.debug('Set mirrored: %s', self.test_mirrored)
        self.display_facade.set_mirrored(self.test_mirrored)
        logging.debug('Switched from %s to %s mode', from_mode, to_mode)
        time.sleep(self.WAIT_TIME)
        self.check_external_resolution()


    def reboot_device(self, plugged_before, plugged_after):
        """Reboot DUT

        @param plugged_before: a boolean, plugged status before reboot
        @param plugged_after: a boolean, plugged status after reboot

        """

        boot_id = self.host.get_boot_id()
        self.chameleon_port.set_plug(plugged_before)
        logging.debug('Reboot...')
        self.host.reboot(wait=False)
        time.sleep(self.WAIT_TIME)
        self.host.test_wait_for_shutdown(self.REBOOT_TIMEOUT)
        self.host.test_wait_for_boot(boot_id)
        self.chameleon_port.set_plug(plugged_after)


    def test_suspend_resume(self, plugged_before_suspend,
                            plugged_after_suspend, plugged_after_resume):
        """Suspends and resumes the DUT with different connections status
        before suspend, after suspend, and after resume

        @param plugged_before_suspend: a boolean, plugged before suspend
        @param plugged_after_suspend: a boolean, plugged after suspend
        @param plugged_after_resume: a boolean, plugged after resume

        """
        boot_id = self.host.get_boot_id()
        # Plug before suspend
        self.chameleon_port.set_plug(plugged_before_suspend)
        time.sleep(self.WAIT_TIME)
        logging.debug('Going to suspend, for %d seconds...',
                     self.SUSPEND_DURATION)
        time_before_suspend = time.time()
        self.display_facade.suspend_resume_bg(self.SUSPEND_DURATION)

        # Confirm DUT suspended.
        self.host.test_wait_for_sleep(self.SUSPEND_TIMEOUT)
        if plugged_before_suspend is not plugged_after_suspend:
            self.chameleon_port.set_plug(plugged_after_suspend)

        current_time = time.time()
        sleep_time = (self.SUSPEND_DURATION -
                      (current_time - time_before_suspend))
        logging.debug('Wait for %.2f seconds...', sleep_time)
        time.sleep(sleep_time)

        self.host.test_wait_for_resume(boot_id, self.RESUME_TIMEOUT)
        logging.debug('Resumed ')

        if plugged_after_resume is not plugged_after_suspend:
            self.chameleon_port.set_plug(plugged_after_resume)


    def check_external_display(self):
        """Display status check"""
        # Check connector and test image
        if self.screen_test.check_external_display_connected(
                self.connector_used, self.errors) is None:
            self.screen_test.test_screen_with_image(
                    self.resolution, self.test_mirrored, self.errors)
        # Check for crashes.
        if self.is_crash_data_present():
            self.errors.append('Crash data is detected on DUT')
        # Check for errors
        if self.errors:
            raise error.TestFail('; '.join(set(self.errors)))


    def get_edids_filepaths(self):
        """Gets the EDID data files for the connector type used"""
        if self.connector_used.startswith('HDMI'):
            first_edid,second_edid = self.EDID_FILE_NAMES[0]
        elif self.connector_used.startswith('DP'):
            first_edid,second_edid = self.EDID_FILE_NAMES[1]
        first_edid = os.path.join(self.bindir, 'test_data/edids', first_edid)
        second_edid = os.path.join(self.bindir, 'test_data/edids', second_edid)
        return (first_edid, second_edid)


    def check_external_resolution(self):
        """Checks the external screen resolution."""
        # Wait video stable, making sure CrOS switches to a proper resolution.
        self.chameleon_port.wait_video_input_stable()
        # Get the resolution for the edid applied
        self.resolution = utils.wait_for_value_changed(
                self.display_facade.get_external_resolution,
                old_value=self.resolution)
        if self.resolution is None:
            self.resolution = utils.wait_for_value_changed(
                    self.display_facade.get_external_resolution,
                    old_value=None)
            if self.resolution is None:
                raise error.TestFail('No external display detected on DUT')

        logging.debug('External display resolution: %dx%d', *self.resolution)


    def apply_edid(self, edid_file):
        """Apply EDID from a file

        @param edid_file: file path to edid data

        """
        self.display_facade.apply_edid(edid.Edid.from_file(edid_file))


    def dock_dut(self):
        """Close lid(assumes device is connected to chameleon)"""
        board = self.host.get_board().split(':')[1]
        logging.debug('Docking the DUT!')
        if board not in self.NO_LID_BOARDS:
            self.host.servo.lid_close()
            time.sleep(self.WAIT_TIME)
            return True
        else:
            logging.debug('DUT does not dock!')
            return False


    def undock_dut(self):
        """Open the lid"""
        self.host.servo.lid_open()
        time.sleep(self.WAIT_TIME)


    def run_once(self, host, test_mirrored=False):
        self.host = host
        self.test_mirrored = test_mirrored
        self.errors = []
        self.resolution = None

        # Check the servo object
        if self.host.servo is None:
            raise error.TestError('Invalid servo object found on the host.')

        # Remove any crash data before test procedure
        if self.is_crash_data_present():
            self.remove_crash_data()

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

        chameleon_board.reset()
        finder = chameleon_port_finder.ChameleonVideoInputFinder(
                chameleon_board, display_facade)
        for chameleon_port in finder.iterate_all_ports():
            self.run_test_on_port(chameleon_port, display_facade)


    def run_test_on_port(self, chameleon_port, display_facade):
        """Run the test on the given Chameleon port.

        @param chameleon_port: a ChameleonPorts object.
        @param display_facade: a display facade object.
        """
        self.chameleon_port = chameleon_port
        self.display_facade = display_facade
        self.screen_test = chameleon_screen_test.ChameleonScreenTest(
                chameleon_port, display_facade, self.outputdir)

        self.connector_used = self.display_facade.get_external_connector_name()
        first_edid, second_edid = self.get_edids_filepaths()

        # Set first monitor/EDID and tracked resolution
        with self.chameleon_port.use_edid_file(first_edid):
            self.check_external_resolution()
            # Set main display mode for the test
            logging.debug('Set mirrored: %s', self.test_mirrored)
            self.display_facade.set_mirrored(self.test_mirrored)

            logging.debug('- Stage  1 - reboot')
            # Reboot the device as connected and login
            self.reboot_device(plugged_before=True, plugged_after=True)
            # Check status
            self.check_external_display()

            logging.debug('- Stage  2 - dock-undock-switch mode and back')
            # Dock and undock (close lid and open lid)
            if self.dock_dut():
                self.undock_dut();

            # Switch mode
            self.switch_display_mode()
            # Switch mode back
            self.switch_display_mode()
            self.check_external_display()

            # Suspend and resume as currently plugged
            logging.debug('- Stage  3 - suspend-resume')
            self.test_suspend_resume(plugged_before_suspend=True,
                                     plugged_after_suspend=True,
                                     plugged_after_resume=True)

            # Check status
            self.check_external_display()

            logging.debug('- Stage  4 - unplug-suspend-plug-resume')
            # Unplug-Suspend-Plug-Resume
            self.test_suspend_resume(plugged_before_suspend=False,
                                     plugged_after_suspend=True,
                                     plugged_after_resume=True)
            # Check status
            self.check_external_display()

            logging.debug('- Stage  5 - suspend-unplug-resume-plug')
            # Suspens-Unplug-Resume-Plug
            self.test_suspend_resume(plugged_before_suspend=True,
                                     plugged_after_suspend=False,
                                     plugged_after_resume=True)
            # Check status
            self.check_external_display()

            logging.debug('- Stage  6 - dock-unplug1/suspend-plug2-undock')
            # Docked mode(close lid)
            if self.dock_dut():
                logging.debug('Unplug display')
                # Unplug, thus DUT should suspend
                self.chameleon_port.set_plug(False)
                self.host.test_wait_for_sleep(self.SUSPEND_TIMEOUT)
                logging.debug('DUT is suspended')

        # Plug the second monitor while suspended
        with self.chameleon_port.use_edid_file(second_edid):
            self.chameleon_port.set_plug(True)

            # Resume(open lid), doesn't hurt if DUT is not docked
            self.undock_dut()
            self.host.wait_up(self.RESUME_TIMEOUT)

            # Set mode back to mirror after resuming with diff monitor
            if self.test_mirrored:
                self.switch_display_mode()
            else:
                # Update the resolution
                self.check_external_resolution()

            # Check status
            self.check_external_display()

            logging.debug('- Stage  7 - unplug2-plug1')
            # Unplug and plug the original monitor
            self.chameleon_port.set_plug(False)

        with self.chameleon_port.use_edid_file(first_edid):
            self.chameleon_port.set_plug(True)

            # Update the resolution
            self.check_external_resolution()

            # Check status
            self.check_external_display()
