# -*- 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 factory
from autotest_lib.client.bin import factory_ui_lib as ful
from autotest_lib.client.bin import test
from autotest_lib.client.bin.input.input_device import *
from autotest_lib.client.common_lib import error
from autotest_lib.client.common_lib import utils
from autotest_lib.client.common_lib.error import CmdError


_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__)
