# Copyright 2015 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 glob
import logging
import os
import subprocess
import tempfile
import time

from autotest_lib.client.bin import utils
from autotest_lib.client.common_lib import error


class Device(object):
    """Information about a specific input device."""
    def __init__(self, input_type):
        self.input_type = input_type  # e.g. 'touchpad'
        self.emulated = False  # Whether device is real or not
        self.emulation_process = None  # Process of running emulation
        self.name = 'unknown'  # e.g. 'Atmel maXTouch Touchpad'
        self.fw_id = None  # e.g. '6.0'
        self.hw_id = None  # e.g. '90.0'
        self.node = None  # e.g. '/dev/input/event4'
        self.device_dir = None  # e.g. '/sys/class/input/event4/device/device'

    def __str__(self):
        s = '%s:' % self.input_type
        s += '\n  Name: %s' % self.name
        s += '\n  Node: %s' % self.node
        s += '\n  hw_id: %s' % self.hw_id
        s += '\n  fw_id: %s' % self.fw_id
        s += '\n  Emulated: %s' % self.emulated
        return s


class InputPlayback(object):
    """
    Provides an interface for playback and emulating peripherals via evemu-*.

    Example use: player = InputPlayback()
                 player.emulate(property_file=path_to_file)
                 player.find_connected_inputs()
                 player.playback(path_to_file)
                 player.blocking_playback(path_to_file)
                 player.close()

    """

    _DEFAULT_PROPERTY_FILES = {'mouse': 'mouse.prop',
                               'keyboard': 'keyboard.prop'}
    _PLAYBACK_COMMAND = 'evemu-play --insert-slot0 %s < %s'

    # Define the overhead (500 ms) elapsed for launching evemu-play and the
    # latency from event injection to the first event read by Chrome Input
    # thread.
    _PLAYBACK_OVERHEAD_LATENCY = 0.5

    # Define a keyboard as anything with any keys #2 to #248 inclusive,
    # as defined in the linux input header.  This definition includes things
    # like the power button, so reserve the "keyboard" label for things with
    # letters/numbers and define the rest as "other_keyboard".
    _MINIMAL_KEYBOARD_KEYS = ['1', 'Q', 'SPACE']
    _KEYBOARD_KEYS = [
            '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 'MINUS', 'EQUAL',
            'BACKSPACE', 'TAB', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O',
            'P', 'LEFTBRACE', 'RIGHTBRACE', 'ENTER', 'LEFTCTRL', 'A', 'S', 'D',
            'F', 'G', 'H', 'J', 'K', 'L', 'SEMICOLON', 'APOSTROPHE', 'GRAVE',
            'LEFTSHIFT', 'BACKSLASH', 'Z', 'X', 'C', 'V', 'B', 'N', 'M',
            'COMMA', 'DOT', 'SLASH', 'RIGHTSHIFT', 'KPASTERISK', 'LEFTALT',
            'SPACE', 'CAPSLOCK', 'F1', 'F2', 'F3', 'F4', 'F5', 'F6', 'F7', 'F8',
            'F9', 'F10', 'NUMLOCK', 'SCROLLLOCK', 'KP7', 'KP8', 'KP9',
            'KPMINUS', 'KP4', 'KP5', 'KP6', 'KPPLUS', 'KP1', 'KP2', 'KP3',
            'KP0', 'KPDOT', 'ZENKAKUHANKAKU', '102ND', 'F11', 'F12', 'RO',
            'KATAKANA', 'HIRAGANA', 'HENKAN', 'KATAKANAHIRAGANA', 'MUHENKAN',
            'KPJPCOMMA', 'KPENTER', 'RIGHTCTRL', 'KPSLASH', 'SYSRQ', 'RIGHTALT',
            'LINEFEED', 'HOME', 'UP', 'PAGEUP', 'LEFT', 'RIGHT', 'END', 'DOWN',
            'PAGEDOWN', 'INSERT', 'DELETE', 'MACRO', 'MUTE', 'VOLUMEDOWN',
            'VOLUMEUP', 'POWER', 'KPEQUAL', 'KPPLUSMINUS', 'PAUSE', 'SCALE',
            'KPCOMMA', 'HANGEUL', 'HANGUEL', 'HANJA', 'YEN', 'LEFTMETA',
            'RIGHTMETA', 'COMPOSE', 'STOP', 'AGAIN', 'PROPS', 'UNDO', 'FRONT',
            'COPY', 'OPEN', 'PASTE', 'FIND', 'CUT', 'HELP', 'MENU', 'CALC',
            'SETUP', 'WAKEUP', 'FILE', 'SENDFILE', 'DELETEFILE', 'XFER',
            'PROG1', 'PROG2', 'WWW', 'MSDOS', 'COFFEE', 'SCREENLOCK',
            'DIRECTION', 'CYCLEWINDOWS', 'MAIL', 'BOOKMARKS', 'COMPUTER',
            'BACK', 'FORWARD', 'CLOSECD', 'EJECTCD', 'EJECTCLOSECD', 'NEXTSONG',
            'PLAYPAUSE', 'PREVIOUSSONG', 'STOPCD', 'RECORD', 'REWIND', 'PHONE',
            'ISO', 'CONFIG', 'HOMEPAGE', 'REFRESH', 'EXIT', 'MOVE', 'EDIT',
            'SCROLLUP', 'SCROLLDOWN', 'KPLEFTPAREN', 'KPRIGHTPAREN', 'NEW',
            'REDO', 'F13', 'F14', 'F15', 'F16', 'F17', 'F18', 'F19', 'F20',
            'F21', 'F22', 'F23', 'F24', 'PLAYCD', 'PAUSECD', 'PROG3', 'PROG4',
            'DASHBOARD', 'SUSPEND', 'CLOSE', 'PLAY', 'FASTFORWARD', 'BASSBOOST',
            'PRINT', 'HP', 'CAMERA', 'SOUND', 'QUESTION', 'EMAIL', 'CHAT',
            'SEARCH', 'CONNECT', 'FINANCE', 'SPORT', 'SHOP', 'ALTERASE',
            'CANCEL', 'BRIGHTNESSDOWN', 'BRIGHTNESSUP', 'MEDIA',
            'SWITCHVIDEOMODE', 'KBDILLUMTOGGLE', 'KBDILLUMDOWN', 'KBDILLUMUP',
            'SEND', 'REPLY', 'FORWARDMAIL', 'SAVE', 'DOCUMENTS', 'BATTERY',
            'BLUETOOTH', 'WLAN', 'UWB', 'UNKNOWN', 'VIDEO_NEXT', 'VIDEO_PREV',
            'BRIGHTNESS_CYCLE', 'BRIGHTNESS_AUTO', 'BRIGHTNESS_ZERO',
            'DISPLAY_OFF', 'WWAN', 'WIMAX', 'RFKILL', 'MICMUTE']

    _WACOM_VENDOR_ID = '2d1f'

    def __init__(self):
        self.devices = {}
        self._emulated_device = None


    def has(self, input_type):
        """Return True/False if device has a input of given type.

        @param input_type: string of type, e.g. 'touchpad'

        """
        return input_type in self.devices


    def _get_input_events(self):
        """Return a list of all input event nodes."""
        return glob.glob('/dev/input/event*')


    def emulate(self, input_type='mouse', property_file=None):
        """
        Emulate the given input (or default for type) with evemu-device.

        Emulating more than one of the same device type will only allow playback
        on the last one emulated.  The name of the last-emulated device is
        noted to be sure this is the case.

        Property files are made with the evemu-describe command,
        e.g. 'evemu-describe /dev/input/event12 > property_file'.

        @param input_type: 'mouse' or 'keyboard' to use default property files.
                           Need not be specified if supplying own file.
        @param property_file: Property file of device to be emulated.  Generate
                              with 'evemu-describe' command on test image.

        """
        new_device = Device(input_type)
        new_device.emulated = True

        # Checks for any previous emulated device and kills the process
        self.close()

        if not property_file:
            if input_type not in self._DEFAULT_PROPERTY_FILES:
                raise error.TestError('Please supply a property file for input '
                                      'type %s' % input_type)
            current_dir = os.path.dirname(os.path.realpath(__file__))
            property_file = os.path.join(
                    current_dir, self._DEFAULT_PROPERTY_FILES[input_type])
        if not os.path.isfile(property_file):
            raise error.TestError('Property file %s not found!' % property_file)

        with open(property_file) as fh:
            name_line = fh.readline()  # Format "N: NAMEOFDEVICE"
            new_device.name = name_line[3:-1]

        logging.info('Emulating %s %s (%s).', input_type, new_device.name,
                     property_file)
        num_events_before = len(self._get_input_events())
        new_device.emulation_process = subprocess.Popen(
                ['evemu-device', property_file], stdout=subprocess.PIPE)

        self._emulated_device = new_device

        # Ensure there are more input events than there were before.
        try:
            expected = num_events_before + 1
            exception = error.TestError('Error emulating %s!' % input_type)
            utils.poll_for_condition(
                    lambda: len(self._get_input_events()) == expected,
                    exception=exception)
        except error.TestError as e:
            self.close()
            raise e


    def _find_device_properties(self, device):
        """Return string of properties for given node.

        @return: string of properties.

        """
        with tempfile.NamedTemporaryFile() as temp_file:
            filename = temp_file.name
            evtest_process = subprocess.Popen(['evtest', device],
                                              stdout=temp_file)

            def find_exit():
                """Polling function for end of output."""
                interrupt_cmd = 'grep "interrupt to exit" %s | wc -l' % filename
                line_count = utils.run(interrupt_cmd).stdout.strip()
                return line_count != '0'

            utils.poll_for_condition(find_exit)
            evtest_process.kill()
            temp_file.seek(0)
            props = temp_file.read()
        return props


    def _determine_input_type(self, props):
        """Find input type (if any) from a string of properties.

        @return: string of type, or None

        """
        if props.find('REL_X') >= 0 and props.find('REL_Y') >= 0:
            if (props.find('ABS_MT_POSITION_X') >= 0 and
                props.find('ABS_MT_POSITION_Y') >= 0):
                return 'multitouch_mouse'
            else:
                return 'mouse'
        if props.find('ABS_X') >= 0 and props.find('ABS_Y') >= 0:
            if (props.find('BTN_STYLUS') >= 0 or
                props.find('BTN_STYLUS2') >= 0 or
                props.find('BTN_TOOL_PEN') >= 0):
                return 'stylus'
            if (props.find('ABS_PRESSURE') >= 0 or
                props.find('BTN_TOUCH') >= 0):
                if (props.find('BTN_LEFT') >= 0 or
                    props.find('BTN_MIDDLE') >= 0 or
                    props.find('BTN_RIGHT') >= 0 or
                    props.find('BTN_TOOL_FINGER') >= 0):
                    return 'touchpad'
                else:
                    return 'touchscreen'
            if props.find('BTN_LEFT') >= 0:
                return 'touchscreen'
        if props.find('KEY_') >= 0:
            for key in self._MINIMAL_KEYBOARD_KEYS:
                if props.find('KEY_%s' % key) >= 0:
                    return 'keyboard'
            for key in self._KEYBOARD_KEYS:
                if props.find('KEY_%s' % key) >= 0:
                    return 'other_keyboard'
        return


    def _get_contents_of_file(self, filepath):
        """Return the contents of the given file.

        @param filepath: string of path to file

        @returns: contents of file.  Assumes file exists.

        """
        return utils.run('cat %s' % filepath).stdout.strip()


    def _get_vendor_id(self, node_dir):
        """Gets the vendor ID of an input device, given its node directory.

        @param node_dir: the directory for the input node in sysfs (e.g.
                         /sys/class/input/event1)

        @returns: the vendor ID, as a string of four lower-case hex digits.
        """
        vendor_id_path = os.path.join(node_dir, 'device/id/vendor')
        if not os.path.exists(vendor_id_path):
            raise error.TestError('Could not read vendor ID for ' + node_dir)
        return self._get_contents_of_file(vendor_id_path).lower()


    def _find_input_name(self, device_dir, name=None):
        """Find the associated input* name for the given device directory.

        E.g. given '/dev/input/event4', return 'input3'.

        @param device_dir: the device directory.
        @param name: the device name.


        @returns: string of the associated input name.

        """
        input_names = glob.glob(os.path.join(device_dir, 'input', 'input*'))
        for input_name in input_names:
            name_path = os.path.join(input_name, 'name')
            if not os.path.exists(name_path):
                continue
            if name == self._get_contents_of_file(name_path):
                return os.path.basename(input_name)
        # Raise if name could not be matched.
        logging.error('Input names found(%s): %s', device_dir, input_names)
        raise error.TestError('Could not match input* to this device!')


    def _find_device_ids_for_styluses(self, node_dir, device_dir, name=None):
        """Find the fw_id and hw_id for the stylus in the given directory.

        @param node_dir: the directory for the input node in sysfs (e.g.
                         /sys/class/input/event1)
        @param device_dir: the device directory.
        @param name: the device name.

        @returns: firmware ID, hardware ID for this device. Since styluses don't
                  really have hardware IDs, this will actually be 'usi' or
                  'wacom' depending on the stylus type. Firmware ID may be None.

        """
        if self._get_vendor_id(node_dir) != self._WACOM_VENDOR_ID:
            # The stylus device only has a distinct hardware and firmware ID if
            # it's a Wacom digitizer. Otherwise, a USI stylus is being used, in
            # which case it's handled by the touchscreen controller. So, there's
            # no point in looking for a firmware ID unless the stylus has a
            # Wacom vendor ID.
            return None, 'usi'

        hw_id = 'wacom' # Wacom styluses don't actually have hwids.
        fw_id = None

        # Find fw_id for wacom styluses via wacom_flash command.  Arguments
        # to this command are wacom_flash (dummy placeholder arg) -a (i2c name)
        # Find i2c name if any /dev/i2c-* link to this device's input event.
        input_name = self._find_input_name(device_dir, name)
        i2c_paths = glob.glob('/dev/i2c-*')
        for i2c_path in i2c_paths:
            class_folder = i2c_path.replace('dev', 'sys/class/i2c-adapter')
            input_folder_path = os.path.join(class_folder, '*', '*',
                                             'input', input_name)
            contents_of_input_folder = glob.glob(input_folder_path)
            if len(contents_of_input_folder) != 0:
                i2c_name = i2c_path[len('/dev/'):]
                cmd = 'wacom_flash dummy -a %s' % i2c_name
                # Do not throw an exception if wacom_flash does not exist.
                result = utils.run(cmd, ignore_status=True)
                if result.exit_status == 0:
                    fw_id = result.stdout.split()[-1]
                break

        if fw_id == '':
            fw_id = None
        return fw_id, hw_id


    def _find_device_ids(self, node_dir, device_dir, input_type, name):
        """Find the fw_id and hw_id for the given device directory.

        Finding fw_id and hw_id applicable only for touchpads, touchscreens,
        and styluses.

        @param node_dir: the directory for the input node in sysfs (e.g.
                         /sys/class/input/event1)
        @param device_dir: the device directory.
        @param input_type: string of input type.
        @param name: string of input name.

        @returns: firmware id, hardware id

        """
        fw_id, hw_id = None, None

        if not device_dir or input_type not in ['touchpad', 'touchscreen',
                                                'stylus']:
            return fw_id, hw_id
        if input_type == 'stylus':
            return self._find_device_ids_for_styluses(node_dir, device_dir,
                                                      name)

        # Touch devices with custom drivers usually save this info as a file.
        fw_filenames = ['fw_version', 'firmware_version', 'firmware_id']
        for fw_filename in fw_filenames:
            fw_path = os.path.join(device_dir, fw_filename)
            if os.path.exists(fw_path):
                if fw_id:
                    logging.warning('Found new potential fw_id when previous '
                                    'value was %s!', fw_id)
                fw_id = self._get_contents_of_file(fw_path)

        hw_filenames = ['hw_version', 'product_id', 'board_id']
        for hw_filename in hw_filenames:
            hw_path = os.path.join(device_dir, hw_filename)
            if os.path.exists(hw_path):
                if hw_id:
                    logging.warning('Found new potential hw_id when previous '
                                    'value was %s!', hw_id)
                hw_id = self._get_contents_of_file(hw_path)

        # Hw_ids for Weida and 2nd gen Synaptics are different.
        if not hw_id:
            id_folder = os.path.abspath(os.path.join(device_dir, '..', 'id'))
            product_path = os.path.join(id_folder, 'product')
            vendor_path = os.path.join(id_folder, 'vendor')

            if os.path.isfile(product_path):
                product = self._get_contents_of_file(product_path)
                if name.startswith('WD'): # Weida ts, e.g. sumo
                    if os.path.isfile(vendor_path):
                        vendor = self._get_contents_of_file(vendor_path)
                        hw_id = vendor + product
                else: # Synaptics tp or ts, e.g. heli, lulu, setzer
                    hw_id = product

        if not fw_id:
            # Fw_ids for 2nd gen Synaptics can only be found via rmi4update.
            # See if any /dev/hidraw* link to this device's input event.
            input_name = self._find_input_name(device_dir, name)
            hidraws = glob.glob('/dev/hidraw*')
            for hidraw in hidraws:
                class_folder = hidraw.replace('dev', 'sys/class/hidraw')
                input_folder_path = os.path.join(class_folder, 'device',
                                                 'input', input_name)
                if os.path.exists(input_folder_path):
                    fw_id = utils.run('rmi4update -p -d %s' % hidraw,
                                      ignore_status=True).stdout.strip()
                    if fw_id == '':
                        fw_id = None
                    break

        return fw_id, hw_id


    def find_connected_inputs(self):
        """Determine the nodes of all present input devices, if any.

        Cycle through all possible /dev/input/event* and find which ones
        are touchpads, touchscreens, mice, keyboards, etc.
        These nodes can be used for playback later.
        If the type of input is already emulated, prefer that device. Otherwise,
        prefer the last node found of that type (e.g. for multiple touchpads).
        Record the found devices in self.devices.

        """
        self.devices = {}  # Discard any previously seen nodes.

        input_events = self._get_input_events()
        for event in input_events:
            properties = self._find_device_properties(event)
            input_type = self._determine_input_type(properties)
            if input_type:
                new_device = Device(input_type)
                new_device.node = event

                class_folder = event.replace('dev', 'sys/class')
                name_file = os.path.join(class_folder, 'device', 'name')
                if os.path.isfile(name_file):
                    name = self._get_contents_of_file(name_file)
                logging.info('Found %s: %s at %s.', input_type, name, event)

                # If a particular device is expected, make sure name matches.
                if (self._emulated_device and
                    self._emulated_device.input_type == input_type):
                    if self._emulated_device.name != name:
                        continue
                    else:
                        new_device.emulated = True
                        process = self._emulated_device.emulation_process
                        new_device.emulation_process = process
                new_device.name = name

                # Find the devices folder containing power info
                # e.g. /sys/class/event4/device/device
                # Search that folder for hwid and fwid
                device_dir = os.path.join(class_folder, 'device', 'device')
                if os.path.exists(device_dir):
                    new_device.device_dir = device_dir
                    new_device.fw_id, new_device.hw_id = self._find_device_ids(
                            class_folder, device_dir, input_type,
                            new_device.name)

                if new_device.emulated:
                    self._emulated_device = new_device

                self.devices[input_type] = new_device
                logging.debug(self.devices[input_type])


    def playback(self, filepath, input_type='touchpad'):
        """Playback a given input file.

        Create input file using evemu-record.
        E.g. 'evemu-record $NODE -1 > $FILENAME'

        @param filepath: path to the input file on the DUT.
        @param input_type: name of device type; 'touchpad' by default.
                           Types are returned by the _determine_input_type()
                           function.
                           input_type must be known. Check using has().

        """
        assert(input_type in self.devices)
        node = self.devices[input_type].node
        logging.info('Playing back finger-movement on %s, file=%s.', node,
                     filepath)
        utils.run(self._PLAYBACK_COMMAND % (node, filepath))


    def blocking_playback(self, filepath, input_type='touchpad'):
        """Playback a given set of inputs and sleep for duration.

        The input file is of the format <name>\nE: <time> <input>\nE: ...
        Find the total time by the difference between the first and last input.

        @param filepath: path to the input file on the DUT.
        @param input_type: name of device type; 'touchpad' by default.
                           Types are returned by the _determine_input_type()
                           function.
                           input_type must be known. Check using has().

        """
        with open(filepath) as fh:
            lines = fh.readlines()
            start = float(lines[0].split(' ')[1])
            end = float(lines[-1].split(' ')[1])
            sleep_time = end - start + self._PLAYBACK_OVERHEAD_LATENCY
        start_time = time.time()
        self.playback(filepath, input_type)
        end_time = time.time()
        elapsed_time = end_time - start_time
        if elapsed_time < sleep_time:
            sleep_time -= elapsed_time
            logging.info('Blocking for %s seconds after playback.', sleep_time)
            time.sleep(sleep_time)


    def blocking_playback_of_default_file(self, filename, input_type='mouse'):
        """Playback a default file and sleep for duration.

        Use a default gesture file for the default keyboard/mouse, saved in
        this folder.
        Device should be emulated first.

        @param filename: the name of the file (path is to this folder).
        @param input_type: name of device type; 'mouse' by default.
                           Types are returned by the _determine_input_type()
                           function.
                           input_type must be known. Check using has().

        """
        current_dir = os.path.dirname(os.path.realpath(__file__))
        gesture_file = os.path.join(current_dir, filename)
        self.blocking_playback(gesture_file, input_type=input_type)


    def close(self):
        """Kill emulation if necessary."""
        if self._emulated_device:
            num_events_before = len(self._get_input_events())
            device_name = self._emulated_device.name

            self._emulated_device.emulation_process.kill()

            # Ensure there is one fewer input event before returning.
            try:
                expected = num_events_before - 1
                utils.poll_for_condition(
                        lambda: len(self._get_input_events()) == expected,
                        exception=error.TestError())
            except error.TestError as e:
                logging.warning('Could not kill emulated %s!', device_name)

            self._emulated_device = None


    def __enter__(self):
        """Allow usage in 'with' statements."""
        return self


    def __exit__(self, exc_type, exc_val, exc_tb):
        """Release resources on completion of a 'with' statement."""
        self.close()
