# Copyright (c) 2012 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 logging, threading, time

from autotest_lib.client.common_lib.cros import crash_detector
from autotest_lib.server import autotest, test
from autotest_lib.client.common_lib import error

_CLIENT_TERMINATION_FILE_PATH = '/tmp/simple_login_exit'
_LONG_TIMEOUT = 200
_LOWER_USB_PORT = 'usb_mux_sel3'
_SUSPEND_TIME = 30
_UPPER_USB_PORT = 'usb_mux_sel1'
_WAIT_DELAY = 15

# servo v4.1 controls
_AUX_USB_PORT = 'aux_usbkey_mux'
_IMAGE_USB_PORT = 'image_usbkey_mux'


class platform_ExternalUsbPeripherals(test.test):
    """Uses servo to repeatedly connect/remove USB devices during boot."""
    version = 1


    def getPluggedUsbDevices(self):
        """Determines the external USB devices plugged

        @returns plugged_list: List of plugged usb devices names

        """
        lsusb_output = self.host.run('lsusb').stdout.strip()
        items = lsusb_output.split('\n')
        plugged_list = []
        unnamed_device_count = 1
        for item in items:
            columns = item.split(' ')
            if len(columns) == 6 or len(' '.join(columns[6:]).strip()) == 0:
                logging.debug('Unnamed device located, adding generic name.')
                name = 'Unnamed device %d' % unnamed_device_count
                unnamed_device_count += 1
            else:
                name = ' '.join(columns[6:]).strip()
            plugged_list.append(name)
        return plugged_list


    def plug_peripherals(self, on=True):
        """Setting USB mux_3 plug status

        @param on: Connect the servo-usb port to DUT(plug) or to servo(unplug)

        """
        switch = 'dut_sees_usbkey'
        if not on:
            switch = 'servo_sees_usbkey'
        self.host.servo.set(self.plug_port, switch)
        self.pluged_status = on


    def client_login(self, client_exit):
        """Login i.e. runs running client test

        @exception TestFail failed to login within timeout.

        """
        self.autotest_client.run_test(self.client_autotest,
                                      exit_without_logout=client_exit)


    def action_login(self, login_client_exit=True):
        """Login i.e. runs running client login

        @param login_client_exit: Exit after login flag.

        """
        thread = threading.Thread(target=self.client_login,
                                  args = (login_client_exit, ))
        thread.start()
        time.sleep(_WAIT_DELAY)


    def action_logout(self):
        """Logout i.e. runs running client test

        @exception TestFail failed to logout within timeout.

        """
        self.host.run('touch %s' % _CLIENT_TERMINATION_FILE_PATH)
        time.sleep(_WAIT_DELAY)


    def wait_for_cmd_output(self, cmd, check, timeout, timeout_msg):
        """Waits till command output is meta

        @param cmd: executed command
        @param check: string to be checked for in cmd output
        @param timeout: max time in sec to wait for output
        @param timeout_msg: timeout failure message

        @returns True if check is found in command output; False otherwise
        """
        start_time = int(time.time())
        time_delta = 0
        command = '%s %s' % (cmd, check)
        logging.debug('Command: %s', command)
        while(self.host.run(command, ignore_status=True).exit_status != 0):
            time_delta = int(time.time()) - start_time
            if time_delta > timeout:
                self.add_failure('%s - %d sec' % (timeout_msg, timeout))
                return False
            time.sleep(0.5)
        logging.debug('Succeeded in :%d sec', time_delta)
        return True


    def suspend_for_time(self, suspend_time=_SUSPEND_TIME):
        """Calls the host method suspend with suspend_time argument.

        @param suspend_time: time to suspend the device for.

        """
        try:
            self.host.suspend(suspend_time=suspend_time)
        except error.AutoservSuspendError:
            pass


    def action_suspend(self):
        """Suspend i.e. powerd_dbus_suspend and wait

        @returns boot_id for the following resume
        """
        boot_id = self.host.get_boot_id()
        thread = threading.Thread(target=self.suspend_for_time)
        thread.start()
        self.host.test_wait_for_sleep(_LONG_TIMEOUT)
        logging.debug('--- Suspended')
        self.suspend_status = True
        return boot_id


    def action_resume(self, boot_id):
        """Resume i.e. press power key and wait

        @param boot_id: boot id obtained prior to suspending

        """
        self.host.test_wait_for_resume(boot_id, _LONG_TIMEOUT)
        logging.debug('--- Resumed')
        self.suspend_status = False


    def close_lid(self):
        """Close lid through servo to suspend the device."""
        boot_id = self.host.get_boot_id()
        logging.info('Closing lid...')
        self.host.servo.lid_close()
        self.host.test_wait_for_sleep(_LONG_TIMEOUT)
        self.suspend_status = True
        return boot_id


    def open_lid(self, boot_id):
        """Open lid through servo to resume."""
        logging.info('Opening lid...')
        self.host.servo.lid_open()
        self.host.test_wait_for_resume(boot_id, _LONG_TIMEOUT)
        self.suspend_status = False


    def crash_not_detected(self):
        """Finds new crash files and adds to failures list if any

        @returns True if there were not crashes; False otherwise
        """
        crash_files = self.detect_crash.get_new_crash_files()
        if crash_files:
            self.add_failure('CRASH DETECTED: %s' % str(crash_files))
            return False
        return True


    def check_plugged_usb_devices(self):
        """Checks the plugged peripherals match device list.

        @returns True if expected USB peripherals are detected; False otherwise
        """
        result = True
        if self.pluged_status and self.usb_list != None:
            # Check for mandatory USb devices passed by usb_list flag
            for usb_name in self.usb_list:
                found = self.wait_for_cmd_output(
                    'lsusb | grep -E ', usb_name, _WAIT_DELAY * 4,
                    'Not detecting %s' % usb_name)
                result = result and found
        time.sleep(_WAIT_DELAY)
        on_now = self.getPluggedUsbDevices()
        if self.pluged_status:
            if not self.diff_list.issubset(on_now):
                missing = str(self.diff_list.difference(on_now))
                self.add_failure('Missing connected peripheral(s) '
                                 'when plugged: %s ' % missing)
                result = False
        else:
            present = self.diff_list.intersection(on_now)
            if len(present) > 0:
                self.add_failure('Still presented peripheral(s) '
                                 'when unplugged: %s ' % str(present))
                result = False
        return result


    def check_usb_peripherals_details(self):
        """Checks the effect from plugged in USB peripherals.

        @returns True if command line output is matched successfuly; Else False
        """
        usb_check_result = True
        for cmd in self.usb_checks.keys():
            out_match_list = self.usb_checks.get(cmd)
            if cmd.startswith('loggedin:'):
                if not self.login_status:
                    continue
                cmd = cmd.replace('loggedin:', '')
            board = self.host.get_board().split(':')[1].lower()
            # Run the usb check command
            for out_match in out_match_list:
                match_result = self.wait_for_cmd_output(
                    cmd, out_match, _WAIT_DELAY * 4,
                    'USB CHECKS DETAILS failed at %s %s:' % (cmd, out_match))
                usb_check_result = usb_check_result and match_result
        return usb_check_result


    def check_status(self):
        """Performs checks after each action:
            - for USB detected devices
            - for generated crash files
            - peripherals effect checks on cmd line

        @returns True if all of the iteration checks pass; False otherwise.
        """
        result = True
        if not self.suspend_status:
            # Detect the USB peripherals
            result = self.check_plugged_usb_devices()
            # Check for crash files
            if self.crash_check:
                result = result and self.crash_not_detected()
            if self.pluged_status and (self.usb_checks != None):
                # Check for plugged USB devices details
                result = result and self.check_usb_peripherals_details()
        return result


    def add_failure(self, reason):
        """ Adds a failure reason to list of failures to be reported at end

        @param reason: failure reason to record

        """
        if self.action_step is not None:
            self.fail_reasons.append('%s FAILS - %s' %
                                     (self.action_step, reason))


    def check_connected_peripherals(self):
        """ Verifies there are connected usb devices on servo

        @raise error.TestError: if no peripherals are shown
        """

        # Collect USB peripherals when unplugged
        self.plug_peripherals(False)
        time.sleep(_WAIT_DELAY)
        off_list = self.getPluggedUsbDevices()

        # Collect USB peripherals when plugged
        self.plug_peripherals(True)
        time.sleep(_WAIT_DELAY * 2)
        on_list = self.getPluggedUsbDevices()

        self.diff_list = set(on_list).difference(set(off_list))
        if len(self.diff_list) == 0:
            # Fail if no devices detected after
            raise error.TestError('No connected devices were detected. Make '
                                  'sure the devices are connected to USB_KEY '
                                  'and DUT_HUB1_USB on the servo board.')
        logging.debug('Connected devices list: %s', self.diff_list)


    def prep_servo_for_test(self):
        """Connects servo to DUT  and sets servo ports

        @returns port as string to plug/unplug the specific port
        """
        if 'servo_v4p1' in self.servo_type:
            port = _AUX_USB_PORT
            self.host.servo.set(_IMAGE_USB_PORT, 'servo_sees_usbkey')
        else:
            port = _LOWER_USB_PORT
            self.host.servo.switch_usbkey('dut')
            self.host.servo.set('dut_hub1_rst1','off')
            self.host.servo.set(_UPPER_USB_PORT, 'servo_sees_usbkey')
            self.host.servo.set('usb_mux_oe2', 'off')
            self.host.servo.set('usb_mux_oe4', 'off')
        time.sleep(_WAIT_DELAY)
        return port


    def cleanup(self):
        """Disconnect servo hub"""
        self.plug_peripherals(False)
        self.action_logout()
        if 'servo_v4p1' not in self.servo_type:
            self.host.servo.set('dut_hub1_rst1','on')
        self.host.run('reboot now', ignore_status=True)
        self.host.test_wait_for_boot()


    def run_once(self, host, client_autotest, action_sequence, repeat,
                 usb_list=None, usb_checks=None,
                 crash_check=False):
        self.client_autotest = client_autotest
        self.host = host
        self.autotest_client = autotest.Autotest(self.host)
        self.usb_list = usb_list
        self.usb_checks = usb_checks
        self.crash_check = crash_check

        self.suspend_status = False
        self.login_status = False
        self.fail_reasons = list()
        self.action_step = None

        self.servo_type = self.host.servo.get_servo_type()

        self.plug_port = self.prep_servo_for_test()

        # Unplug, plug, compare usb peripherals, and leave plugged.
        self.check_connected_peripherals()

        action_sequence = action_sequence.upper()
        # Check for if board type is NOT chromebook and skip lid_close_open tests
        if (not (host.get_board_type() == 'CHROMEBOOK')) and \
                ('CLOSELID' in action_sequence):
            raise error.TestNAError('No lid on DUT. Test Skipped')
        actions = action_sequence.split(',')
        boot_id = 0
        self.detect_crash = crash_detector.CrashDetector(self.host)
        self.detect_crash.remove_crash_files()

        for iteration in xrange(1, repeat + 1):
            step = 0
            for action in actions:
                step += 1
                action = action.strip()
                self.action_step = 'STEP %d.%d. %s' % (iteration, step, action)
                logging.info(self.action_step)

                if action == 'RESUME':
                    self.action_resume(boot_id)
                    time.sleep(_WAIT_DELAY)
                elif action == 'OPENLID':
                    self.open_lid(boot_id)
                    time.sleep(_WAIT_DELAY)
                elif action == 'UNPLUG':
                    self.plug_peripherals(False)
                elif action == 'PLUG':
                    self.plug_peripherals(True)
                elif self.suspend_status == False:
                    if action.startswith('LOGIN'):
                        if self.login_status:
                            logging.debug('Skipping login. Already logged in.')
                            continue
                        else:
                            self.action_login('LOGOUT' not in actions)
                            self.login_status = True
                    elif action == 'LOGOUT':
                        if self.login_status:
                            self.action_logout()
                            self.login_status = False
                        else:
                            logging.debug('Skipping logout. Not logged in.')
                    elif action == 'REBOOT':
                        self.host.reboot()
                        time.sleep(_WAIT_DELAY * 3)
                        self.login_status = False
                    elif action == 'SUSPEND':
                        boot_id = self.action_suspend()
                    elif action == 'CLOSELID':
                        boot_id = self.close_lid()
                else:
                    logging.info('WRONG ACTION: %s .', self.action_step)
                self.check_status()

            if self.fail_reasons:
                raise error.TestFail('Failures reported: %s' %
                                     str(self.fail_reasons))
