# -*- coding: utf-8 -*-
#
# Copyright (c) 2010 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.


# DESCRIPTION :
#
# Intended for use during manufacturing to validate that the touchpad
# is functioning properly.

import cairo
import gobject
import gtk
import os
import pty
import re
import subprocess
import sys
import time

from cmath import pi
from glob import glob
from gtk import gdk

from autotest_lib.client.bin import test
from autotest_lib.client.bin.input.input_device import *
from autotest_lib.client.common_lib.error import CmdError
from autotest_lib.client.common_lib import error
from autotest_lib.client.common_lib import utils
from autotest_lib.client.cros import factory
from autotest_lib.client.cros.factory import ui as ful


_X_SEGMENTS = 5
_Y_SEGMENTS = 4

_X_TP_OFFSET = 12
_Y_TP_OFFSET = 12
_TP_WIDTH = 396
_TP_HEIGHT = 212
_TP_SECTOR_WIDTH = (_TP_WIDTH / _X_SEGMENTS) - 1
_TP_SECTOR_HEIGHT = (_TP_HEIGHT / _Y_SEGMENTS) - 1

_X_SP_OFFSET = 428
_SP_WIDTH = 15

_F_RADIUS = 21

_X_OF_OFFSET = 486 + _F_RADIUS + 2
_Y_OF_OFFSET = 54 + _F_RADIUS + 2

_X_TFL_OFFSET = 459 + _F_RADIUS + 2
_X_TFR_OFFSET = 513 + _F_RADIUS + 2
_Y_TF_OFFSET = 117 + _F_RADIUS + 2


class TouchpadTest:

    def __init__(self, tp_image, drawing_area):
        self._tp_image = tp_image
        self._drawing_area = drawing_area
        self._motion_grid = {}
        for x in range(_X_SEGMENTS):
            for y in range(_Y_SEGMENTS):
                self._motion_grid['%d,%d' % (x, y)] = False
        self._scroll_array = {}
        for y in range(_Y_SEGMENTS):
            self._scroll_array[y] = False
        self._l_click = False
        self._r_click = False
        self._of_z_rad = 0
        self._tf_z_rad = 0

    def calc_missing_string(self):
        missing = []
        missing_motion_sectors = sorted(
            i for i, v in self._motion_grid.items() if v is False)
        if missing_motion_sectors:
            missing.append('Missing following motion sectors\n'
                           '未偵測到下列位置的觸控移動訊號 [%s]' %
                           ', '.join(missing_motion_sectors))
        missing_scroll_segments = sorted(
            str(i) for i, v in self._scroll_array.items() if v is False)
        if missing_scroll_segments:
            missing.append('Missing following scroll segments\n'
                           '未偵測到下列位置的觸控捲動訊號 [%s]' %
                           ', '.join(missing_scroll_segments))
        if not self._l_click:
            missing.append('Missing left click\n'
                           '沒有偵測到左鍵被按下，請檢修')
        if not self._r_click:
            missing.append('Missing right click\n'
                           '沒有偵測到右鍵被按下，請檢修')
        return '\n'.join(missing)

    def device_event(self, x, y, z, fingers, left, right):
        x_seg = int(round(x / (1.0 / float(_X_SEGMENTS - 1))))
        y_seg = int(round(y / (1.0 / float(_Y_SEGMENTS - 1))))
        z_rad = int(round(z / (1.0 / float(_F_RADIUS - 1))))

        index = '%d,%d' % (x_seg, y_seg)

        assert(index in self._motion_grid)
        assert(y_seg in self._scroll_array)

        new_stuff = False

        if left and not self._l_click:
            self._l_click = True
            self._of_z_rad = _F_RADIUS
            factory.log('ok left click')
            new_stuff = True
        elif right and not self._r_click:
            self._r_click = True
            self._tf_z_rad = _F_RADIUS
            factory.log('ok right click')
            new_stuff = True

        if fingers == 1 and not self._motion_grid[index]:
            self._motion_grid[index] = True
            new_stuff = True
        elif fingers == 2 and not self._scroll_array[y_seg]:
            self._scroll_array[y_seg] = True
            new_stuff = True

        if fingers == 1 and not self._l_click and z_rad != self._of_z_rad:
            self._of_z_rad = z_rad
            new_stuff = True
        elif fingers == 2 and not self._r_click and z_rad != self._tf_z_rad:
            self._tf_z_rad = z_rad
            new_stuff = True

        if new_stuff:
            self._drawing_area.queue_draw()

        if not self.calc_missing_string():
            factory.log('completed successfully')
            gtk.main_quit()

    def expose_event(self, widget, event):
        context = widget.window.cairo_create()

        # Fill context with factory UI default background color.
        context.set_source_rgb(0, 0, 0)
        context.paint()

        # Show touchpad image as the background.
        context.set_source_surface(self._tp_image, 0, 0)
        context.paint()

        context.set_source_rgba(*ful.RGBA_GREEN_OVERLAY)

        for index in self._motion_grid:
            if not self._motion_grid[index]:
                continue
            ind_x, ind_y = map(int, index.split(','))
            x = _X_TP_OFFSET + (ind_x * (_TP_SECTOR_WIDTH + 1))
            y = _Y_TP_OFFSET + (ind_y * (_TP_SECTOR_HEIGHT + 1))
            coords = (x, y, _TP_SECTOR_WIDTH, _TP_SECTOR_HEIGHT)
            context.rectangle(*coords)
            context.fill()

        for y_seg in self._scroll_array:
            if not self._scroll_array[y_seg]:
                continue
            y = _Y_TP_OFFSET + (y_seg * (_TP_SECTOR_HEIGHT + 1))
            coords = (_X_SP_OFFSET, y, _SP_WIDTH, _TP_SECTOR_HEIGHT)
            context.rectangle(*coords)
            context.fill()

        if not self._l_click:
            context.set_source_rgba(*ful.RGBA_YELLOW_OVERLAY)

        context.arc(_X_OF_OFFSET, _Y_OF_OFFSET, self._of_z_rad, 0.0, 2.0 * pi)
        context.fill()

        if self._l_click and not self._r_click:
            context.set_source_rgba(*ful.RGBA_YELLOW_OVERLAY)

        context.arc(_X_TFL_OFFSET, _Y_TF_OFFSET, self._tf_z_rad, 0.0, 2.0 * pi)
        context.fill()
        context.arc(_X_TFR_OFFSET, _Y_TF_OFFSET, self._tf_z_rad, 0.0, 2.0 * pi)
        context.fill()

        return True

    def button_press_event(self, widget, event):
        factory.log('button_press_event %d,%d' % (event.x, event.y))
        return True

    def button_release_event(self, widget, event):
        factory.log('button_release_event %d,%d' % (event.x, event.y))
        return True

    def motion_event(self, widget, event):
        factory.log('motion_event %d,%d' % (event.x, event.y))
        return True


class SynClient:
    _SETTINGS_CMDLINE = '/usr/bin/synclient -l'
    _CMDLINE = '/usr/bin/synclient -m 50'

    def __init__(self, test):
        self._test = test
        try:
            settings_data = utils.system_output(self._SETTINGS_CMDLINE)
        except CmdError as e:
            raise error.TestError('Failure on "%s" [%d]' %
                                  (self._SETTINGS_CMDLINE,
                                   e.args[1].exit_status))
        settings = {}
        for line in settings_data.split('\n'):
            cols = [x for x in line.rstrip().split(' ') if x]
            if len(cols) != 3 or cols[1] != '=':
                continue
            settings[cols[0]] = cols[2]
        try:
            for key, attr in (('LeftEdge',   '_xmin'),
                              ('RightEdge',  '_xmax'),
                              ('TopEdge',    '_ymin'),
                              ('BottomEdge', '_ymax'),
                              ('FingerLow',  '_zmin'),
                              ('FingerHigh', '_zmax')):
                v = float(settings[key])
                setattr(self, attr, v)
        except KeyError as e:
            factory.log('Field %s does not exist' % e.args)
            raise error.TestNAError("Can't detect all hardware information")
        except ValueError as e:
            factory.log('Invalid literal format of %s: %s' % (key, e.args[0]))
            raise error.TestNAError("Can't understand all hardware information")
        try:
            self._proc = subprocess.Popen(self._CMDLINE.split(),
                                          stdout=subprocess.PIPE,
                                          stderr=subprocess.PIPE)
        except OSError as e:
            raise error.TestError('Failure on launching "%s"' % self._CMDLINE)
        # delay before we poll
        time.sleep(0.1)
        if self._proc.poll() is not None:
            if self._proc.returncode != 0:
                raise error.TestError('Failure on "%s" [%d]' %
                                      (self._CMDLINE, self._proc.returncode))
            else:
                raise error.TestError('Termination unexpected on "%s"' %
                                      self._CMDLINE)
        gobject.io_add_watch(self._proc.stdout, gobject.IO_IN, self.recv)

    def recv(self, src, cond):
        ''' header and data look as:
            time     x    y   z f  w  l r u d m     multi  gl gm gr gdx gdy
           0.000  3532 3807   0 0  0  0 0 0 0 0  00000000
        '''
        data = self._proc.stdout.readline().split()
        if data[0] == 'time':
            return True
        if len(data) != 12:
            factory.log('unknown data : %d, %s' % (len(data), data))
            return True
        data_x, data_y, data_z, f, w, l, r = data[1:8]
        x = sorted([self._xmin, float(data_x), self._xmax])[1]
        x = (x - self._xmin) / (self._xmax - self._xmin)
        y = sorted([self._ymin, float(data_y), self._ymax])[1]
        y = (y - self._ymin) / (self._ymax - self._ymin)
        z = sorted([self._zmin, float(data_z), self._zmax])[1]
        z = (z - self._zmin) / (self._zmax - self._zmin)
        # Detect right click button or alt right click
        alt_r = int(r) or (int(l) and int(f) == 2)
        self._test.device_event(x, y, z, int(f), int(l), alt_r)
        return True

    def quit(self):
        factory.log('killing SynClient ...')
        self._proc.kill()
        factory.log('dead')


class EvdevClient:

    def __init__(self, test, device):
        self._test = test
        self.ev = InputEvent()
        self.device = device
        gobject.io_add_watch(device.f, gobject.IO_IN, self.recv)

        self._xmin = device.get_x_min()
        self._xmax = device.get_x_max()
        self._ymin = device.get_y_min()
        self._ymax = device.get_y_max()
        self._zmin = device.get_pressure_min()
        self._zmax = device.get_pressure_max()

        factory.log('x:(%d : %d), y:(%d : %d), z:(%d, %d)' %
                    (self._xmin, self._xmax, self._ymin, self._ymax,
                     self._zmin, self._zmax))

    def _to_percent(self, val, _min, _max):
        bound = sorted([_min, float(val), _max])[1]
        return (bound - _min) / (_max - _min)

    def recv(self, src, cond):
        try:
            self.ev.read(src)
        except:
            raise error.TestError('Error reading events from %s' %
                                  self.device.path)
        if not self.device.process_event(self.ev):
            return True

        f = self.device.get_num_fingers()
        if f == 0:
           return True

        x = self.device.get_x()
        y = self.device.get_y()
        z = self.device.get_pressure()
        l = self.device.get_left()
        # Detect right click button or alt right click
        r = self.device.get_right() or (l and f == 2)

        # Convert raw coordinate to % of range.
        x_pct = self._to_percent(x, self._xmin, self._xmax)
        y_pct = self._to_percent(y, self._ymin, self._ymax)
        z_pct = self._to_percent(z, self._zmin, self._zmax)

        factory.log('x=%f y=%f z=%f f=%d l=%d r=%d' %
                    (x_pct, y_pct, z_pct, f, l, r))

        self._test.device_event(x_pct, y_pct, z_pct, f, l, r)
        return True

    def quit(self):
        if self.device and self.device.f and not self.device.f.closed:
            factory.log('Closing %s...' % self.device.path)
            self.device.f.close()


class SynControl:
    ''' Use syncontrol to read packets and pass them to TouchpadTest '''
    # A typical packet looks like
    #     x: 4357, y: 2973, z: 48, w: 4, dx: 0, dy: 0,
    #     finger_index: 0, left_button: 0, right_button: 0
    pattern = (u'x: \d+, y: \d+, z: \d+, w: \d+, dx: -?\d+, dy: -?\d+, '
               u'finger_index: \d+, left_button: \d+, right_button: \d+')
    _SYNCONTROL = '/opt/Synaptics/bin/syncontrol'
    _CMDLINE = '%s packets' % _SYNCONTROL

    # Set the default min and max values for typical bezel limits and Z.
    # These are approximate values, and may be different in different models.
    # Use these values only if they cannot be derived from the diag file.
    _X_RANGE = (1400, 5400)
    _Y_RANGE = (1300, 4300)
    _Z_RANGE = (0, 255)

    def __init__(self, test):
        self._test = test
        # Read settings from diag file
        self._get_settings()

        # Open pty to avoid buffered output in subprocess.Popen
        master, slave = pty.openpty()
        self.pty_stdout = os.fdopen(master)

        try:
            self._proc = subprocess.Popen(self._CMDLINE, shell=True,
                                          stdout=slave, stderr=slave)
        except OSError as e:
            raise error.TestError('Failure on launching "%s"' % self._CMDLINE)

        if self._proc.poll() is not None:
            if self._proc.returncode != 0:
                raise error.TestError('Failure on "%s" [%d]' %
                                      (self._CMDLINE, self._proc.returncode))
            else:
                raise error.TestError('Termination unexpected on "%s"' %
                                      self._CMDLINE)
        gobject.io_add_watch(self.pty_stdout, gobject.IO_IN, self.recv)

    def _get_settings(self):
        ''' Get min x, min y, max x, max y, and max z '''

        def _delete_diag_files(tmp_dir, diag_file):
            for f in glob(os.path.join(tmp_dir, diag_file)):
                if os.path.isfile(f):
                    os.remove(f)

        tmp_dir = '/tmp'
        diag_file = 'SynDiag*'
        diag_cmd = 'HOME=%s %s diag' % (tmp_dir, self._SYNCONTROL)

        # delete any old diag file
        _delete_diag_files(tmp_dir, diag_file)

        # Execute syncontrol diag to dump touchpad settings
        utils.system(diag_cmd)

        # Initialize the settings
        # Note: there is no min z in the diag file. Set it to default value 0.
        self._xmin, self._xmax = self._X_RANGE
        self._ymin, self._ymax = self._Y_RANGE
        self._zmin, self._zmax = self._Z_RANGE
        found_z = False
        found_rect = False

        # A bezel rectangle in diag file looks as:
        #       'Bezel Rectangle (1374, 1324) (5538, 4464)'
        # The max z in diag file looks as:
        #       'Maximum Z       255'
        rect_str = u'Bezel Rectangle\s+\((\d+),\s*(\d+)\)\s*\((\d+),\s*(\d+)\)'

        diag = glob(os.path.join(tmp_dir, diag_file))
        if diag != []:
            factory.log('diag_file: %s' % diag)
            with open(diag[0]) as f:
                for line in f:
                    # Read min x, min y, max x, max y from the bezel rectangle
                    if not found_rect and line.startswith('Bezel Rectangle'):
                        s = re.search(rect_str, line)
                        if s is not None:
                            self._xmin = int(s.group(1))
                            self._ymin = int(s.group(2))
                            self._xmax = int(s.group(3))
                            self._ymax = int(s.group(4))
                            found_rect = True
                    # Read max z
                    elif not found_z and line.startswith('Maximum Z'):
                        self._zmax = int(line.split()[-1])
                        found_z = True
                    if found_rect and found_z:
                        break

        # delete the diag file
        _delete_diag_files(tmp_dir, diag_file)

    def recv(self, src, cond):
        line = self.pty_stdout.readline()
        if line == '':
            return True

        # check packet validity
        if re.search(self.pattern, line) is None:
            factory.log('  Invalid packet skipped: %s' % line)
            return True

        data = line.split(',')
        (data_x, data_y, data_z, data_w, data_dx, data_dy, data_finger_index,
                 data_left_button, data_right_button) = \
                 (d.split(':')[-1].strip().rstrip('\n') for d in data)

        x = sorted([self._xmin, float(data_x), self._xmax])[1]
        x = (x - self._xmin) / (self._xmax - self._xmin)
        y = sorted([self._ymin, float(data_y), self._ymax])[1]
        y = (y - self._ymin) / (self._ymax - self._ymin)
        y = 1 - y
        z = sorted([self._zmin, float(data_z), self._zmax])[1]
        z = (z - self._zmin) / (self._zmax - self._zmin)
        fingers = int(data_finger_index) + 1
        left_button = int(data_left_button)
        right_button = int(data_right_button)
        self._test.device_event(x, y, z, fingers, left_button, right_button)
        return True

    def quit(self):
        factory.log('killing SynControl ...')
        self._proc.kill()
        factory.log('dead')


class factory_Touchpad(test.test):
    version = 1
    preserve_srcdir = True

    def run_once(self):

        factory.log('%s run_once' % self.__class__)

        os.chdir(self.srcdir)
        tp_image = cairo.ImageSurface.create_from_png('touchpad.png')
        image_size = (tp_image.get_width(), tp_image.get_height())

        drawing_area = gtk.DrawingArea()

        test = TouchpadTest(tp_image, drawing_area)

        drawing_area.set_size_request(*image_size)
        drawing_area.connect('expose_event', test.expose_event)
        drawing_area.connect('button-press-event', test.button_press_event)
        drawing_area.connect('button-release-event', test.button_release_event)
        drawing_area.connect('motion-notify-event', test.motion_event)
        drawing_area.add_events(gdk.EXPOSURE_MASK |
                                gdk.BUTTON_PRESS_MASK |
                                gdk.BUTTON_RELEASE_MASK |
                                gdk.POINTER_MOTION_MASK)

        test_widget = gtk.VBox()
        test_widget.set_spacing(20)
        test_widget.pack_start(drawing_area, False, False)
        usage_label = ful.make_label(
                '1. Move one finger across entire touchpad surface\n'
                '2. Scroll from top to bottom of pad with two fingers\n'
                '3. Click touchpad with one finger\n'
                '4. Click touchpad with two fingers\n')
        test_widget.pack_start(usage_label, False, False)

        raw_dev = glob('/dev/serio_raw*')
        # Check if synaptics closed source kernel driver is used
        if len(raw_dev) > 0:
            factory.log('Syncontrol: found device: %s' % raw_dev[0])
            touchpad = SynControl(test)
        else:
            # Detect an evdev compatible touchpad device.
            # TODO(djkurtz): Use gudev to detect touchpad
            for evdev in glob('/dev/input/event*'):
                device = InputDevice(evdev)
                if device.is_touchpad():
                    break
            else:
                device = None

            # Using EvdevCient if an evdev compatible touchpad device is found
            if device:
                factory.log('EvdevClient: using %s,  device %s' %
                            (device.name, device.path))
                touchpad = EvdevClient(test, device)
            else:
                factory.log('Using SynClient.')
                touchpad = SynClient(test)

        ful.run_test_widget(self.job, test_widget,
            cleanup_callback=touchpad.quit)

        missing = test.calc_missing_string()
        if missing:
            raise error.TestFail(missing)

        factory.log('%s run_once finished' % self.__class__)
