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

"""Touchpad device module provides some touchpad related attributes."""

import glob
import os
import re

import common_util


class TouchpadDevice:
    """A class about touchpad device properties."""

    def __init__(self, device_node=None):
        self.device_info_file = '/proc/bus/input/devices'
        self.device_node = (device_node if device_node
                                        else self.get_device_node())

    def _re_str(self):
        """Get the regular expression search string for a touchpad device."""
        pattern_str = ('touchpad', 'trackpad', 'cyapa')
        return '(?:%s)' % '|'.join(pattern_str)

    def get_device_node(self):
        """Get the touchpad device node through tpcontrol.

        tpcontrol returns a string like
                  Device Node (244):      "/dev/input/event8"
        """
        cmd = '/opt/google/touchpad/tpcontrol status | grep -i "device node"'
        device_node_str = common_util.simple_system_output(cmd)
        device_node = device_node_str.split(':')[-1].strip().strip('"')
        return device_node

    def get_dimensions_in_mm(self):
        """Get the width and height in mm of the device."""
        (left, right, top, bottom,
                resolution_x, resolution_y) = self.get_resolutions()
        width = float((right - left)) / resolution_x
        height = float((bottom - top)) / resolution_y
        return (width, height)

    def get_resolutions(self, device_description=None):
        """Get the resolutions in x and y axis of the device."""
        _, _, _, _, resolution_x, resolution_y = self.get_abs_axes(
                device_description)
        return (resolution_x, resolution_y)

    def get_edges(self, device_description=None):
        """Get the left, right, top, and bottom edges of the device."""
        left, right, top, bottom, _, _ = self.get_abs_axes(
                device_description)
        return (left, right, top, bottom)

    def get_abs_axes(self, device_description=None):
        """Get information about min, max, and resolution from ABS_X and ABS_Y

        Example of ABS_X:
                A: 00 0 1280 0 0 12
        Example of ABS_y:
                A: 01 0 1280 0 0 12
        """
        pattern = 'A:\s*%s\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)'
        pattern_x = pattern % '00'
        pattern_y = pattern % '01'
        cmd = 'evemu-describe %s' % self.device_node
        if device_description is None:
            device_description = common_util.simple_system_output(cmd)
        found_x = found_y = False
        left = right = top = bottom = None
        resolution_x = resolution_y = None
        if device_description:
            for line in device_description.splitlines():
                if not found_x:
                    result = re.search(pattern_x, line, re.I)
                    if result:
                        left = int(result.group(1))
                        right = int(result.group(2))
                        resolution_x = int(result.group(5))
                        found_x = True
                if not found_y:
                    result = re.search(pattern_y, line, re.I)
                    if result:
                        top = int(result.group(1))
                        bottom = int(result.group(2))
                        resolution_y = int(result.group(5))
                        found_y = True
        return (left, right, top, bottom, resolution_x, resolution_y)

    def get_dimensions(self, device_description=None):
        """Get the dimensions of the touchpad reported size."""
        left, right, top, bottom = self.get_edges(device_description)
        return (right - left, bottom - top)

    def get_display_geometry(self, screen_size, display_ratio):
        """Get a preferred display geometry when running the test."""
        display_ratio = 0.8
        dev_width, dev_height = self.get_dimensions()
        screen_width, screen_height = screen_size

        if 1.0 * screen_width / screen_height <= 1.0 * dev_width / dev_height:
            disp_width = int(screen_width * display_ratio)
            disp_height = int(disp_width * dev_height / dev_width)
            disp_offset_x = 0
            disp_offset_y = screen_height - disp_height
        else:
            disp_height = int(screen_height * display_ratio)
            disp_width = int(disp_height * dev_width / dev_height)
            disp_offset_x = 0
            disp_offset_y = screen_height - disp_height

        return (disp_width, disp_height, disp_offset_x, disp_offset_y)

    def _touchpad_input_name_re_str(self):
        pattern_str = ('touchpad', 'trackpad')
        return '(?:%s)' % '|'.join(pattern_str)

    def get_touchpad_input_dir(self):
        """Get touchpad input directory."""
        input_root_dir = '/sys/class/input'
        input_dirs = glob.glob(os.path.join(input_root_dir, 'input*'))
        re_pattern = re.compile(self._touchpad_input_name_re_str(), re.I)
        for input_dir in input_dirs:
            filename = os.path.join(input_dir, 'name')
            if os.path.isfile(filename):
                with open(filename) as f:
                    for line in f:
                        if re_pattern.search(line) is not None:
                            return input_dir
        return None

    def get_firmware_version(self):
        """Probe the firmware version."""
        input_dir = self.get_touchpad_input_dir()
        device_dir = 'device'

        # Get the re search pattern for firmware_version file name
        fw_list = ('firmware', 'fw')
        ver_list = ('version', 'id')
        sep_list = ('_', '-')
        re_str = '%s%s%s' % ('(?:%s)' % '|'.join(fw_list),
                             '(?:%s)' % '|'.join(sep_list),
                             '(?:%s)' % '|'.join(ver_list))
        re_pattern = re.compile(re_str, re.I)

        if input_dir is not None:
            device_dir = os.path.join(input_dir, 'device', '*')
            for f in glob.glob(device_dir):
                if os.path.isfile(f) and re_pattern.search(f):
                    with open (f) as f:
                        for line in f:
                            return line.strip('\n')
        return 'unknown'
