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

import logging
import os
import pyudev
import re

from autotest_lib.client.bin import test, utils
from autotest_lib.client.common_lib import error
from collections import defaultdict
from operator import attrgetter

def natural_key(string_):
    """
    Derive key for natural sorting.
    @param string_: String to derive sort key for.
    From http://stackoverflow.com/questions/34518/natural-sorting-algorithm.
    """
    return [int(s) if s.isdigit() else s for s in re.split(r'(\d+)', string_)]


class platform_UdevVars(test.test):
    """Verify ChromeOS-specific udev variables."""
    version = 1


    def _input_devices(self):
        """Obtain a list of all /dev/input/event* udev devices."""
        devices = self.udev.list_devices(subsystem='input')
        # only consider the event devices
        devices = filter(attrgetter('device_node'), devices)
        devices = sorted(devices, key=lambda device: natural_key(device.device_node))
        return devices


    def _get_roles(self):
        """Get information on input devices and roles from udev."""
        self.devices_with_role = defaultdict(list)

        logging.debug('Input devices:')
        for device in self._input_devices():
            name = device.parent.attributes.get('name', '')
            logging.debug('  %s [%s]', device.device_node, name)
            role = device.get('POWERD_ROLE', None)
            if role:
                logging.debug('    POWERD_ROLE=%s', role)
                self.devices_with_role[role].append(device)


    def _dump_roles(self):
        """Log devices grouped by role for easier debugging."""
        logging.info('Roles:')
        for role in sorted(self.devices_with_role.keys()):
            for device in self.devices_with_role[role]:
                path = device.device_node
                name = device.parent.attributes.get('name', '')
                logging.info('  %-21s %s [%s]', role + ':', path, name)


    def _dump_udev_attrs(self):
        """Log udev attributes for selected devices to the debug directory."""
        for device in self._input_devices():
            devname = os.path.basename(device.device_node)

            outfile = os.path.join(self.debugdir, "udevattrs.%s" % devname)
            utils.system('udevadm info --attribute-walk --path=%s > %s' % (
                    device.sys_path, outfile))

            outfile = os.path.join(self.debugdir, "udevprops.%s" % devname)
            utils.system('udevadm info --query=property --path=%s > %s' % (
                    device.sys_path, outfile))


    def _verify_roles(self):
        """Verify that POWERD_ROLE was set on devices as expected."""

        # TODO(chromium:410968): Consider moving this to USE flags instead of
        # listing devices here.
        boards_with_touchscreen = ['link', 'samus']
        boards_maybe_touchscreen = ['rambi', 'peppy', 'glimmer', 'clapper',
                                    'nyan_big', 'nyan_blaze', 'expresso']
        boards_chromebox = ['tricky', 'mccloud', 'zako', 'panther', 'beltino',
                            'stumpy']
        boards_aio = ['nyan_kitty', 'tiny', 'anglar', 'monroe']

        expect_keyboard = None
        expect_touchpad = None
        expect_touchscreen = None

        board = utils.get_board()
        if board in boards_chromebox or board in boards_aio:
            expect_keyboard = [0]
            expect_touchpad = [0]
        else:
            expect_keyboard = [1]
            expect_touchpad = [1]

        if board in boards_with_touchscreen:
            expect_touchscreen = [1]
        elif board in boards_maybe_touchscreen:
            expect_touchscreen = [0, 1]
        else:
            expect_touchscreen = [0]

        expected_num_per_role = [
                ('internal_keyboard', expect_keyboard),
                ('internal_touchpad', expect_touchpad),
                ('internal_touchscreen', expect_touchscreen),
            ]

        for role, expected_num in expected_num_per_role:
            num = len(self.devices_with_role[role])
            if num not in expected_num:
                self.errors += 1
                logging.error('POWERD_ROLE=%s is present %d times, expected '
                              'one of %s', role, num, repr(expected_num))

        if len(self.devices_with_role['external_input']) != 0:
            logging.warn('%d external input devices detected',
                         len(self.devices_with_role['external_input']))


    def initialize(self):
        self.udev = pyudev.Context()


    def run_once(self):
        """
        Check that udev variables are assigned correctly by udev rules. In
        particular, verifies that powerd tags are set correctly.
        """
        logging.debug('Board: %s', utils.get_board())
        self._get_roles()
        self._dump_roles()
        self._dump_udev_attrs()

        self.errors = 0
        self._verify_roles()

        if self.errors != 0:
            raise error.TestFail('Verification of udev variables failed; see '
                                 'logs for details')
