# -*- 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 :
#
# This is a factory test to test the LEDs (wifi, battery, etc).


import cairo
import gtk
import pango
import os
import subprocess
import sys
import re

from cmath import pi
from gtk import gdk

from autotest_lib.client.bin import test
from autotest_lib.client.bin import utils
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


_LABEL_STATUS_SIZE = (140, 30)
_LABEL_FONT = pango.FontDescription('courier new condensed 16')
_LABEL_FG = gtk.gdk.color_parse('light green')
_LABEL_UNTESTED_FG = gtk.gdk.color_parse('grey40')

_PATTERN_LABEL_STR = 'pattern / 图样: '

_ORANGE = gtk.gdk.color_parse('orange')

_LED_NAMES = 'sleepled battchgled wlan battfulled powerled 3g'.split()
_ORANGE_LED_NAMES = _LED_NAMES[0:3]
_BLUE_LED_NAMES = _LED_NAMES[3:]

_LED_COUNT = 3
_LED_Y_OFFSET = 10
_LED_X_OFFSETS = [10, 80, 150]
_LED_RADIUS = 18
_SHFL_XYR = {'x':166,'y':20, 'r':9}


def run_led_ctl(led_ctl_path, args):
    rc = subprocess.call([led_ctl_path] + args.split())
    if rc != 1:
        factory.log('%s(%s) failed with rc %s' % (led_ctl_path, args, rc))


def pattern_all_off(led_ctl_fn):
    for n in _LED_NAMES:
        led_ctl_fn('-%s -off' % n)
    return [ful.BLACK, ful.BLACK, ful.BLACK]

def pattern_blue_on(led_ctl_fn):
    pattern_all_off(led_ctl_fn)
    for n in _BLUE_LED_NAMES:
        led_ctl_fn('-%s -on' % n)
    return [ful.BLUE, ful.BLUE, ful.BLUE]

def pattern_orange_on(led_ctl_fn):
    pattern_all_off(led_ctl_fn)
    for n in _ORANGE_LED_NAMES:
        led_ctl_fn('-%s -on' % n)
    return [_ORANGE, _ORANGE, _ORANGE]

_PATTERN_LIST = [
    ('all off', pattern_all_off),
    ('blue on', pattern_blue_on),
    ('orange on', pattern_orange_on),
    ('shift led', False)]


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

    def goto_next_pattern(self):
        if not self._pattern_queue:
            gtk.main_quit()
            return
        self._current_pattern, cb_fn = self._pattern_queue.pop()
        self._status_map[self._current_pattern] = ful.ACTIVE
        if cb_fn:
            led_ctl_fn = lambda args: run_led_ctl(self._led_ctl_path, args)
            self._led_colors = cb_fn(led_ctl_fn)
        else:
            self._pattern_da.connect('expose_event', self.shift_led_expose)
        self._pattern_da.queue_draw()

    def shift_led_expose(self, widget, event):
        context = widget.window.cairo_create()
        context.set_source_surface(self._shf_image, 0, 0)
        context.paint()

        if self._shift_cnt is 2:
            if self._shift_color is ful.BLACK:
                self._shift_color = ful.BLUE
            else:
                self._shift_color = ful.BLACK
            self._shift_cnt = 0
        context.set_source_color(self._shift_color)
        context.arc(_SHFL_XYR['x'], _SHFL_XYR['y'], _SHFL_XYR['r'],
                    0.0, 2.0 * pi)
        context.fill()

    def pattern_expose(self, widget, event):
        context = widget.window.cairo_create()
        context.set_source_surface(self._leds_image, 0, 0)
        context.paint()
        for led_index in range(_LED_COUNT):
            color = self._led_colors[led_index]
            x_offset = _LED_X_OFFSETS[led_index] + _LED_RADIUS + 3
            y_offset = _LED_Y_OFFSET + _LED_RADIUS + 3
            context.set_source_color(color)
            context.arc(x_offset, y_offset, _LED_RADIUS, 0.0, 2.0 * pi)
            context.fill()

    def quit(self):
        factory.log('releasing LEDs ...')
        run_led_ctl(self._led_ctl_path, '-ledrelease')

    def label_status_expose(self, widget, event, name=None):
        status = self._status_map[name]
        widget.set_text(status)
        widget.modify_fg(gtk.STATE_NORMAL, ful.LABEL_COLORS[status])

    def make_pattern_label_box(self, name):
        eb = gtk.EventBox()
        eb.modify_bg(gtk.STATE_NORMAL, ful.BLACK)
        label_status = gtk.Label(ful.UNTESTED)
        label_status.set_size_request(*_LABEL_STATUS_SIZE)
        label_status.set_alignment(0, 0.5)
        label_status.modify_font(_LABEL_FONT)
        label_status.modify_fg(gtk.STATE_NORMAL, _LABEL_UNTESTED_FG)
        expose_cb = lambda *x: self.label_status_expose(*x, **{'name':name})
        label_status.connect('expose_event', expose_cb)
        label_en = gtk.Label(name)
        label_en.set_alignment(1, 0.5)
        label_en.modify_font(_LABEL_FONT)
        label_en.modify_fg(gtk.STATE_NORMAL, _LABEL_FG)
        label_sep = gtk.Label(' : ')
        label_sep.set_alignment(0.5, 0.5)
        label_sep.modify_font(_LABEL_FONT)
        label_sep.modify_fg(gtk.STATE_NORMAL, _LABEL_FG)
        hbox = gtk.HBox()
        hbox.pack_end(label_status, False, False)
        hbox.pack_end(label_sep, False, False)
        hbox.pack_end(label_en, False, False)
        eb.add(hbox)
        return eb

    def key_release_callback(self, widget, event):
        if event.keyval == gtk.keysyms.Tab:
            self._status_map[self._current_pattern] = ful.FAILED
            self.goto_next_pattern()
        elif event.keyval == gtk.keysyms.Return:
            self._status_map[self._current_pattern] = ful.PASSED
            self.goto_next_pattern()
        elif self._current_pattern.startswith("shift") and \
                event.keyval == gtk.keysyms.Shift_L:
            self._shift_cnt += 1
            self._pattern_da.queue_draw()
        return True

    def register_callbacks(self, window):
        window.connect('key-release-event', self.key_release_callback)
        window.add_events(gdk.KEY_RELEASE_MASK)

    def _get_embedded_controller_vendor(self):
        # example output of superiotool:
        #  Found Nuvoton WPCE775x (id=0x05, rev=0x02) at 0x2e
        re_vendor = re.compile(r'Found (\w*)')
        vendor = []
        res = utils.system_output('superiotool', ignore_status=True).split('\n')
        for line in res:
            match = re_vendor.search(line)
            if match:
                vendor.append(match.group(1))
        return vendor

    def run_once(self, led_ctl_path=None):

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

        ec_vendor = self._get_embedded_controller_vendor()
        if len(ec_vendor) == 0:
            raise error.TestNAError('No embedded controller vendor found')
        if 'Nuvoton' not in ec_vendor:
            raise error.TestNAError('Currently not supported embedded controllers: %s' %
                                    ', '.join(ec_vendor))

        self._led_ctl_path = led_ctl_path
        if not os.path.exists(self._led_ctl_path):
            raise error.TestNAError('Command %s does not exist' %
                                    self._led_ctl_path)

        self._shift_color = ful.BLACK
        self._shift_cnt = 0

        os.chdir(self.srcdir)
        try:
            image = cairo.ImageSurface.create_from_png('leds.png')
        except cairo.Error as e:
            raise error.TestNAError('Error while opening leds.png: %s' %
                                    e.message)
        image_size = (image.get_width(), image.get_height())
        self._leds_image = image

        image = cairo.ImageSurface.create_from_png('shf.png')
        self._shf_image = image

        self._pattern_queue = [x for x in reversed(_PATTERN_LIST)]
        self._status_map = dict((n, ful.UNTESTED) for n, f in _PATTERN_LIST)

        pattern_da = gtk.DrawingArea()
        pattern_da.set_size_request(*image_size)
        pattern_da.connect('expose_event', self.pattern_expose)
        self._pattern_da = pattern_da

        pattern_label = ful.make_label(_PATTERN_LABEL_STR)

        pattern_box = gtk.HBox()
        pattern_box.pack_start(pattern_label, False, False)
        pattern_box.pack_start(pattern_da, False, False)

        prompt_label = ful.make_label(ful.USER_PASS_FAIL_SELECT_STR)

        subvbox = gtk.VBox()
        for name, cb_fun in _PATTERN_LIST:
            label_box = self.make_pattern_label_box(name)
            subvbox.pack_start(label_box, False, False)

        vbox = gtk.VBox()
        vbox.set_spacing(20)
        vbox.pack_start(prompt_label, False, False)
        vbox.pack_start(pattern_box, False, False)
        vbox.pack_start(subvbox, False, False)

        test_widget = gtk.EventBox()
        test_widget.modify_bg(gtk.STATE_NORMAL, ful.BLACK)
        test_widget.add(vbox)
        self._test_widget = test_widget

        self.goto_next_pattern()

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

        failed_set = set(name for name, status in self._status_map.items()
                         if status is not ful.PASSED)
        if failed_set:
            raise error.TestFail('Some patterns failed\n' \
                                 '以下图样测试未通过: %s' %
                                 ', '.join(failed_set))

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