# -*- coding: utf-8 -*-
#
# 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.


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

import cairo
import gobject
import gtk
import os

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 import error
from autotest_lib.client.cros import factory_setup_modules
from cros.factory.test import factory
from cros.factory.test import ui as ful


_X_SEGMENTS = 15
_Y_SEGMENTS = 12

_X_TS_OFFSET = 12
_Y_TS_OFFSET = 12
_TS_WIDTH = 756
_TS_HEIGHT = 416
_TS_SECTOR_WIDTH = (_TS_WIDTH / _X_SEGMENTS) - 1
_TS_SECTOR_HEIGHT = (_TS_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 TouchscreenTest:

    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._of_z_rad = 0
        self._tf_z_rad = 0

        self._current_x = None
        self._current_y = None

    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))
        return '\n'.join(missing)

    def device_event(self, x, y, z, fingers):
        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)
        self._current_x = x_seg
        self._current_y = y_seg

        self._of_z_rad = z_rad
        self._tf_z_rad = z_rad

        assert(index in self._motion_grid)

        if fingers == 1 and not self._motion_grid[index]:
            self._motion_grid[index] = True

        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 touchscreen 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_TS_OFFSET + (ind_x * (_TS_SECTOR_WIDTH + 1))
            y = _Y_TS_OFFSET + (ind_y * (_TS_SECTOR_HEIGHT + 1))
            coords = (x, y, _TS_SECTOR_WIDTH, _TS_SECTOR_HEIGHT)
            context.rectangle(*coords)
            context.fill()

        if self._current_x is not None:
            context.set_source_rgba(*ful.RGBA_RED_OVERLAY)
            coords = (_X_TS_OFFSET + (self._current_x * (_TS_SECTOR_WIDTH + 1)),
                    _Y_TS_OFFSET + (self._current_y * (_TS_SECTOR_HEIGHT + 1)),
                    _TS_SECTOR_WIDTH, _TS_SECTOR_HEIGHT)
            context.rectangle(*coords)
            context.fill()

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

        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

class EvdevTouchscreen:

    def __init__(self, test, device):
        self._test = test
        self.ev = InputEvent()
        self.device = device

        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))
        gobject.io_add_watch(device.f, gobject.IO_IN, self.recv)

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

        # 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' %
                    (x_pct, y_pct, z_pct, f))

        self._test.device_event(x_pct, y_pct, z_pct, f)
        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 factory_Touchscreen(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('touchscreen.png')
        image_size = (tp_image.get_width(), tp_image.get_height())

        drawing_area = gtk.DrawingArea()

        test = TouchscreenTest(tp_image, drawing_area)

        drawing_area.set_size_request(*image_size)
        drawing_area.connect('expose_event', test.expose_event)
        drawing_area.add_events(gdk.EXPOSURE_MASK)

        test_widget = gtk.VBox()
        test_widget.set_spacing(20)
        test_widget.pack_start(drawing_area, False, False)
        usage_label = ful.make_label(
                'Move one finger across entire touchscreen surface\n')
        test_widget.pack_start(usage_label, False, False)

        # Detect an evdev compatible touchscreen device.
        # TODO(djkurtz): Use gudev to detect touchscreen
        for evdev in glob('/dev/input/event*'):
            device = InputDevice(evdev)
            if device.is_touchscreen():
                # Using EvdevTouchscreen if an evdev compatible touchscreen
                # device is found.
                factory.log('EvdevTouchscreen: using %s,  device %s' %
                            (device.name, device.path))
                touchscreen = EvdevTouchscreen(test, device)
                break
        else:
            raise error.TestFail('No compatible touchscreen device is found\n')

        self._current_x = None
        self._current_y = None

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

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

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