# -*- 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 :
#
# There are test situations that we want to execute certain commands and
# check whether the commands run correctly by human judgement. This is a
# base class provides a generic framework to itemize tests in this category.

import gtk

from autotest_lib.client.bin import test
from autotest_lib.client.cros import factory
from autotest_lib.client.common_lib import error
from autotest_lib.client.common_lib import utils
from autotest_lib.client.cros.factory import task
from autotest_lib.client.cros.factory import ui as ful


def _make_decision_widget(message, key_action_mapping):
    '''Returns a widget that display the message and bind proper functions.

    @param message: Message to display on the widget.
    @param key_release_callback:
        A dict of tuples indicates functions and keys
        in the format {gtk_keyval: (function, function_parameters)}
    @return A widget binds with proper functions.
    '''
    widget = gtk.VBox()
    widget.add(ful.make_label(message))
    def key_release_callback(_, event):
        if event.keyval in key_action_mapping:
            callback, callback_parameters = key_action_mapping[event.keyval]
            callback(*callback_parameters)
            return True

    widget.key_callback = key_release_callback
    return widget


class FactoryLineItemCheckBase(test.test):
    version = 1

    def run_once(self):
        raise NotImplementedError

    def _next_item(self):
        self._item = self._item + 1
        if self._item < len(self._items):
            # Update the UI.
            widget, cmd_line = self._items[self._item]
            self._switch_widget(widget)
            # Execute command after UI is updated.
            if cmd_line:
                task.schedule(self._run_cmd, cmd_line)
        else:
            # No more item.
            gtk.main_quit()

    def _switch_widget(self, widget_to_display):
        if widget_to_display is not self.last_widget:
            if self.last_widget:
                self.last_widget.hide()
                self.test_widget.remove(self.last_widget)
            self.last_widget = widget_to_display
            self.test_widget.add(widget_to_display)
            self.test_widget.show_all()
        else:
            return

    def _register_callbacks(self, window):
        def key_press_callback(widget, event):
            if hasattr(self.last_widget, 'key_callback'):
                return self.last_widget.key_callback(widget, event)
            return False
        window.connect('key-press-event', key_press_callback)
        window.add_events(gtk.gdk.KEY_PRESS_MASK)

    def _run_cmd(self, cmd):
        factory.log('Running command [%s]' % cmd)
        ret = utils.system_output(cmd)
        factory.log('Command returns [%s]' % ret)

    def _fail_test(self, cmd):
        raise error.TestFail('Failed with command [%s]' % cmd)

    def _check_line_items(self, item_tuples):
        factory.log('%s run_once' % self.__class__)
        # Initialize variables.
        self.last_widget = None
        self.item_tuples = item_tuples

        # Line item in (widget, command) format.
        self._items = []

        # Set up the widgets.
        # There are two types of widgets, one gives instructions without
        # judgement, the other decides whether the result matches expectations.
        self.widgets = []
        for idx, _tuple in enumerate(self.item_tuples):
            judge, cmd_line, prompt_message = _tuple
            if judge:
                # Widget involves human judgement.
                key_action_mapping = {
                    gtk.keysyms.Return: (self._next_item, []),
                    gtk.keysyms.Tab: (self._fail_test, [cmd_line])}
                self.widgets.append(_make_decision_widget(
                    prompt_message + ful.USER_PASS_FAIL_SELECT_STR,
                    key_action_mapping))
                self._items.append(
                    (self.widgets[idx], cmd_line))
            else:
                key_action_mapping = {
                    gtk.keysyms.space: (self._next_item, [])}
                self.widgets.append(_make_decision_widget(
                    prompt_message,
                    key_action_mapping))
                self._items.append((self.widgets[idx], None))

            factory.log('Item %d: %s' % (idx, cmd_line))

        self.test_widget = gtk.VBox()
        self._item = -1
        self._next_item()

        ful.run_test_widget(
                self.job,
                self.test_widget,
                window_registration_callback=self._register_callbacks)
