# 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']


    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 _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, device_dir, name=None):
        """Find the fw_id and hw_id for the stylus in the given directory.

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

        @returns: firmware id, hardware id for this device.

        """
        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, 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 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(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(
                            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()
