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

"""Check USB device by running linux command on CfM"""

from __future__ import print_function

import logging
import re
import time
from autotest_lib.client.common_lib.cros.manual import get_usb_devices
from autotest_lib.client.common_lib.cros import power_cycle_usb_util

CORE_DIR_LINES = 3
ATRUS = '18d1:8001'

def check_chrome_logfile(dut):
    """
    Get the latest chrome log file.
    @param dut: The handle of the device under test.
    @returns: the latest chrome log file
    """
    output = None
    logging.info('---Get the latest chrome log file')
    cmd = 'ls -latr /var/log/chrome/chrome'
    try:
        output = dut.run(cmd, ignore_status=True).stdout
    except Exception as e:
        logging.exception('Fail to run command %s.', cmd)
        return None
    logging.info('---cmd: %s', cmd)
    logging.info('---output: %s', output.lower().strip())
    return output

def check_last_reboot(dut):
    """
    Get the last line of eventlog.txt
    @param dut: The handle of the device under test.
    @returns: the last line in eventlog.txt
    """
    output = None
    cmd = 'tail -1 /var/log/eventlog.txt'
    logging.info('---Get the latest reboot log')
    try:
        output = dut.run(cmd, ignore_status=True).stdout
    except Exception as e:
        logging.exception('Fail to run command %s.', cmd)
        return None
    logging.info('---cmd: %s', cmd)
    logging.info('---output: %s', output.lower().strip())
    return output

def check_is_platform(dut, name):
    """
    Check whether CfM is expected platform.
    @param dut: The handle of the device under test.
    @param name: The name of platform
    @returns: True, if CfM's platform is same as expected.
              False, if not.
    """
    cmd = ("cat /var/log/platform_info.txt | grep name | "
           "awk -v N=3 \'{print $N}\'")
    output = dut.run(cmd, ignore_status=True).stdout.split()[0]
    logging.info('---cmd: %s', cmd)
    logging.info('---output: %s', output.lower())
    return output.lower() == name


def get_mgmt_ipv4(dut):
    """
    Get mgmt ipv4 address
    @param dut: The handle of the device under test. Should be initialized in
                 autotest.
    @return: ipv4 address for mgmt interface.
    """
    cmd = 'ifconfig -a | grep eth0 -A 2 | grep netmask'
    try:
        output = dut.run(cmd, ignore_status=True).stdout
    except Exception as e:
        logging.exception('Fail to run command %s.', cmd)
        return None
    ipv4 = re.findall(r"inet\s*([0-9.]+)\s*netmask.*", output)[0]
    return ipv4


def retrieve_usb_devices(dut):
    """
    Populate output of usb-devices on CfM.
    @param dut: handle of CfM under test
    @returns dict of all usb devices detected on CfM.
    """
    usb_devices = (dut.run('usb-devices', ignore_status=True).
                   stdout.strip().split('\n\n'))
    usb_data = get_usb_devices.extract_usb_data(
               '\nUSB-Device\n'+'\nUSB-Device\n'.join(usb_devices))
    return usb_data


def extract_peripherals_for_cfm(usb_data):
    """
    Check CfM has camera, speaker and Mimo connected.
    @param usb_data: dict extracted from output of "usb-devices"
    """
    peripheral_map = {}

    speaker_list = get_usb_devices.get_speakers(usb_data)
    camera_list = get_usb_devices.get_cameras(usb_data)
    display_list = get_usb_devices.get_display_mimo(usb_data)
    controller_list = get_usb_devices.get_controller_mimo(usb_data)
    for pid_vid, device_count in speaker_list.iteritems():
        if device_count > 0:
            peripheral_map[pid_vid] = device_count

    for pid_vid, device_count in camera_list.iteritems():
        if device_count > 0:
            peripheral_map[pid_vid] = device_count

    for pid_vid, device_count in controller_list.iteritems():
        if device_count > 0:
            peripheral_map[pid_vid] = device_count

    for pid_vid, device_count in display_list.iteritems():
        if device_count > 0:
            peripheral_map[pid_vid] = device_count

    for pid_vid, device_count in peripheral_map.iteritems():
        logging.info('---device: %s (%s), count: %d',
                     pid_vid, get_usb_devices.get_device_prod(pid_vid),
                     device_count)

    return peripheral_map


def check_peripherals_for_cfm(peripheral_map):
    """
    Check CfM has one and only one camera,
    one and only one speaker,
    or one and only one mimo.
    @param peripheral_map: dict for connected camera, speaker, or mimo.
    @returns: True if check passes,
              False if check fails.
    """
    peripherals = peripheral_map.keys()

    type_camera = set(peripherals).intersection(get_usb_devices.CAMERA_LIST)
    type_speaker = set(peripherals).intersection(get_usb_devices.SPEAKER_LIST)
    type_controller = set(peripherals).intersection(\
                      get_usb_devices.TOUCH_CONTROLLER_LIST)
    type_panel = set(peripherals).intersection(\
                 get_usb_devices.TOUCH_DISPLAY_LIST)

    # check CfM have one, and only one type camera, huddly and mimo
    if len(type_camera) == 0:
        logging.info('No camera is found on CfM.')
        return False

    if not len(type_camera) == 1:
        logging.info('More than one type of cameras are found on CfM.')
        return False

    if len(type_speaker) == 0:
        logging.info('No speaker is found on CfM.')
        return False

    if not len(type_speaker) == 1:
        logging.info('More than one type of speakers are found on CfM.')
        return False

    if len(type_controller) == 0:
       logging.info('No controller is found on CfM.')
       return False


    if not len(type_controller) == 1:
        logging.info('More than one type of controller are found on CfM.')
        return False

    if len(type_panel) == 0:
        logging.info('No Display is found on CfM.')
        return False

    if not len(type_panel) == 1:
        logging.info('More than one type of displays are found on CfM.')
        return False

    # check CfM have only one camera, huddly and mimo
    for pid_vid, device_count in peripheral_map.iteritems():
        if device_count > 1:
            logging.info('Number of device %s connected to CfM : %d',
                         get_usb_devices.get_device_prod(pid_vid),
                         device_count)
            return False

    return True


def check_usb_enumeration(dut, puts):
    """
    Check USB enumeration for devices
    @param dut: the handle of CfM under test
    @param puts: the list of peripherals under test
    @returns True, none if test passes
             False, errMsg if test test fails
    """
    usb_data = retrieve_usb_devices(dut)
    if not usb_data:
        logging.warning('No usb devices found on DUT')
        return False, 'No usb device found on DUT.'
    else:
        usb_device_list = extract_peripherals_for_cfm(usb_data)
        logging.info('---usb device = %s', usb_device_list)
        if not set(puts).issubset(set(usb_device_list.keys())):
            logging.info('Detect device fails for usb enumeration')
            logging.info('Expect enumerated devices: %s', puts)
            logging.info('Actual enumerated devices: %s',
                         usb_device_list.keys())
            return False, 'Some usb devices are not found.'
        return True, None


def check_usb_interface_initializion(dut, puts):
    """
    Check CfM shows valid interface for all peripherals connected.
    @param dut: the handle of CfM under test
    @param puts: the list of peripherals under test
    @returns True, none if test passes
             False, errMsg if test test fails
    """
    usb_data = retrieve_usb_devices(dut)
    for put in puts:
        number, health = get_usb_devices.is_usb_device_ok(usb_data, put)
        logging.info('---device interface = %d, %s for %s',
                     number, health,  get_usb_devices.get_device_prod(put))
        if '0' in health:
            logging.warning('Device %s has invalid interface', put)
            return False, 'Device {} has invalid interface.'.format(put)
    return True, None


def clear_core_file(dut):
    """clear core files"""
    cmd = "rm -rf /var/spool/crash/*.*"
    try:
        dut.run_output(cmd)
    except Exception as e:
        logging.exception('Fail to clean core files under '
                     '/var/spool/crash')
        logging.exception('Fail to execute %s :', cmd)


def check_process_crash(dut, cdlines):
    """Check whether there is core file."""
    cmd = 'ls -latr /var/spool/crash'
    try:
        core_files_output = dut.run_output(cmd).splitlines()
    except Exception as e:
        logging.exception('Can not find file under /var/spool/crash.')
        logging.exception('Fail to execute %s:', cmd)
        return True,  CORE_DIR_LINES
    logging.info('---%s\n---%s', cmd, core_files_output)
    if len(core_files_output) - cdlines <= 0:
        logging.info('---length of files: %d', len(core_files_output))
        return True, len(core_files_output)
    else:
        return False, len(core_files_output)


def gpio_usb_test(dut, gpio_list, device_list, pause, board):
    """
    Run GPIO test to powercycle usb port.
    @parama dut: handler of CfM,
    @param gpio_list: the list of gpio ports,
    @param device_list: the list of usb devices,
    @param pause: time needs to wait before restoring power to usb port,
                  in seconds
    @param board: board name for CfM
    @returns True
    """
    for device in device_list:
       vid, pid  = device.split(':')
       logging.info('---going to powercyle device %s:%s', vid, pid)
       try:
            power_cycle_usb_util.power_cycle_usb_vidpid(dut, board,
                                                        vid, pid, pause)
       except Exception as e:
           errmsg = 'Fail to power cycle device.'
           logging.exception('%s.', errmsg)
           return False, errmsg

    return True, None


def reboot_test(dut, pause):
    """
    Reboot CfM.
    @parama dut: handler of CfM,
    @param pause: time needs to wait after issuing reboot command, in seconds,

    """
    try:
        dut.reboot()
    except Exception as e:
        logging.exception('Fail to reboot CfM.')
        return False
    logging.info('---reboot done')
    time.sleep(pause)
    return True



def find_last_log(dut, speaker):
    """
    Get the lastlast_lines line for log files.
    @param dut: handler of CfM
    @param speaker: vidpid if speaker.
    @returns: the list of string of the last line of logs.
    """
    last_lines = {
              'messages':[],
              'chrome':[],
              'ui': [],
              'atrus': []
                  }
    logging.debug('Get the last line of log file, speaker %s', speaker)
    try:
        cmd = "tail -1 /var/log/messages | awk -v N=1 '{print $N}'"
        last_lines['messages'] = dut.run_output(cmd).strip().split()[0]
        cmd = "tail -1 /var/log/chrome/chrome | awk -v N=1 '{print $N}'"
        last_lines['chrome'] = dut.run_output(cmd).strip().split()[0]
        cmd = "tail -1 /var/log/ui/ui.LATEST | awk -v N=1 '{print $N}'"
        last_lines['ui']= dut.run_output(cmd)
        if speaker == ATRUS and check_is_platform(dut, 'guado'):
            logging.info('---atrus speaker %s connected to CfM', speaker)
            cmd = 'tail -1 /var/log/atrus.log | awk -v N=1 "{print $N}"'
            last_lines['atrus'] = dut.run_output(cmd).strip().split()[0]
    except Exception as e:
        logging.exception('Fail to get the last line from log files.')
    for item, timestamp in last_lines.iteritems():
        logging.debug('---%s: %s', item, timestamp)
    return last_lines


def collect_log_since_last_check(dut, lastlines, logfile):
    """Collect log file since last check."""
    output = None
    if logfile == "messages":
        cmd ='awk \'/{}/,0\' /var/log/messages'.format(lastlines[logfile])
    if logfile == "chrome":
        cmd ='awk \'/{}/,0\' /var/log/chrome/chrome'.format(lastlines[logfile])
    if logfile == "ui":
        cmd ='awk \'/{}/,0\' /var/log/ui/ui.LATEST'.format(lastlines[logfile])
    if logfile == 'atrus':
         cmd ='awk \'/{}/,0\' /var/log/atrus.log'.format(lastlines[logfile])
    logging.info('---cmd = %s', cmd)
    try:
        output =  dut.run_output(cmd).split('\n')
    except Exception as e:
        logging.exception('Fail to get output from log files.')
    logging.info('---length of log: %d', len(output))
    if not output:
        logging.info('--fail to find match log, check the latest log.')

    if not output:
        if logfile == "messages":
            cmd ='cat /var/log/messages'
        if logfile == "chrome":
            cmd ='cat /var/log/chrome/chrome'
        if logfile == "ui":
            cmd ='cat /var/log/ui/ui.LATEST'
        if logfile == 'atrus':
            cmd ='cat /var/log/atrus.log'
        output =  dut.run_output(cmd).split('\n')
        logging.info('---length of log: %d', len(output))
    return output

def check_log(dut, timestamp, error_list, checkitem, logfile):
    """
    Check logfile does not contain any element in error_list[checkitem].
    """
    error_log_list = []
    logging.info('---now check log %s in file %s', checkitem, logfile)
    output = collect_log_since_last_check(dut, timestamp, logfile)
    for _error in error_list[checkitem]:
         error_log_list.extend([s for s in output if _error in str(s)])
    if not error_log_list:
        return True, None
    else:
        tempmsg = '\n'.join(error_log_list)
        errmsg = 'Error_Found:in_log_file:{}:{}.'.format(logfile, tempmsg)
        logging.info('---%s', errmsg)
        return False, errmsg
