#!/usr/bin/python3
# -*- coding: utf-8 -*-

#  Copyright © 2013  B. Clausius <barcc@gmx.de>
#
#  This program is free software: you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program.  If not, see <http://www.gnu.org/licenses/>.



import sys, os

from PyQt4.QtCore import Qt, QPoint
from PyQt4.QtGui import QDialogButtonBox
from PyQt4.QtTest import QTest


field_functions = {
        'view_editbar':     ('action_editbar', False, lambda widget: widget.isChecked()),
        'view_toolbar':     ('action_toolbar', False, lambda widget: widget.isChecked()),
        'view_statusbar':   ('action_statusbar', False, lambda widget: widget.isChecked()),
        'edit_text':        ('edit_moves', None, lambda widget: str(widget.text())),
        'edit_pos':         ('edit_moves', None, lambda widget: widget.cursorPosition()),
        'game_pos':         ('MainWindow', None, lambda widget: widget.gamestate.all_moves.current_place),
        'game_len':         ('MainWindow', None, lambda widget: len(widget.gamestate.all_moves.moves)),
        'solved':           ('MainWindow', None, lambda widget: widget.gamestate.current_cube_state.is_solved()),
        'sizes':            ('MainWindow', None, lambda widget: widget.gamestate.current_cube_state.model.sizes),
        'rotationx':        ('MainWindow', None, lambda widget: widget.cube_area.rotation_x),
        'rotationy':        ('MainWindow', None, lambda widget: widget.cube_area.rotation_y),
        'selectdlg_exists': ('DialogSelectModel', False, lambda widget: True),
        'selectdlg_visible':('DialogSelectModel', False, lambda widget: widget.isVisible()),
        'dlg_model':        ('combobox_model', None, lambda widget: widget.currentIndex()),
        'lblsize1':         ('label_width', None, lambda widget: widget.isEnabled()),
        'lblsize2':         ('label_heigth', None, lambda widget: widget.isEnabled()),
        'lblsize3':         ('label_depth', None, lambda widget: widget.isEnabled()),
        'size1':            ('spin_size1', None, lambda widget: (widget.value(), widget.isEnabled())),
        'size2':            ('spin_size2', None, lambda widget: (widget.value(), widget.isEnabled())),
        'size3':            ('spin_size3', None, lambda widget: (widget.value(), widget.isEnabled())),
        'dlg_solved':       ('checkbox_solved', None, lambda widget: widget.isChecked()),
        'preferencesdlg_exists': ('DialogPreferences', False, lambda widget: True),
        'preferencesdlg_visible': ('DialogPreferences', False, lambda widget: widget.isVisible()),
        'aboutdlg_exists': ('AboutDialog', False, lambda widget: True),
        'aboutdlg_visible': ('AboutDialog', False, lambda widget: widget.isVisible()),
    }

widget_functions = []

def widget(*wnames, **kwargs):
    fname = kwargs.setdefault('fname', None)
    assert list(kwargs.keys()) == ['fname'], kwargs
    def decorator(func):
        widget_functions.append((wnames, fname or func.__name__, func))
        return func
    return decorator
    
    
@widget('edit_moves')
def edit_moves_text(widget, text, enter=True):
    widget.setText(text)
    if enter:
        widget.returnPressed.emit()
        
edit_moves_key = widget('edit_moves', fname='edit_moves_key')(QTest.keyClick)

@widget('edit_moves')
def edit_moves_key_enter(widget, key, modifiers=Qt.NoModifier):
    QTest.keyClick(widget, key, modifiers)
    QTest.keyClick(widget, Qt.Key_Enter)
    
button_edit_exec_click = widget('button_edit_exec', fname='button_edit_exec_click')(QTest.mouseClick)
button_edit_clear_click = widget('button_edit_clear', fname='button_edit_clear_click')(QTest.mouseClick)

drawingarea_key = widget('drawingarea', fname='drawingarea_key')(QTest.keyClick)

@widget('drawingarea')
def drawingarea_mouse_click(widget, p, button, modifiers=Qt.NoModifier):
    QTest.mouseMove(widget, QPoint(*p))
    QTest.mouseClick(widget, button, modifiers, QPoint(*p), delay=50)
    
@widget('edit_moves', 'drawingarea')
def empty_and_drawingarea_mouse_click(edit_moves, drawingarea, p, button, modifiers=Qt.NoModifier):
    edit_moves_text(edit_moves, '')
    QTest.qWait(50)
    drawingarea_mouse_click(drawingarea, p, button, modifiers)
    
@widget('drawingarea')
def drawingarea_mouse_move(widget, p1, p2, button, modifiers=Qt.NoModifier):
    QTest.mouseMove(widget, QPoint(*p1))
    QTest.mousePress(widget, button, modifiers, QPoint(*p1), delay=50)
    QTest.mouseMove(widget, QPoint(*p2))
    QTest.mouseRelease(widget, button, modifiers, QPoint(*p2))
    
@widget('action_selectmodel')
def dialog_selectmodel(action):
    action.trigger()
    QTest.qWait(200)
    return 'find_qobjects'
    
@widget('combobox_model')
def dialog_selectmodel_changemodel(widget, key):
    if widget.isVisible():
        QTest.keyClick(widget, key, delay=100)
        
@widget('checkbox_solved')
def dialog_selectmodel_checksolved(widget, check):
    if widget.isVisible():
        QTest.qWait(100)
        widget.setChecked(check)
    
@widget('buttonBox')
def dialog_selectmodel_ok(widget):
    if widget.isVisible():
        QTest.qWait(100)
        QTest.mouseClick(widget.button(QDialogButtonBox.Ok), Qt.LeftButton)
        QTest.qWait(100)
    
@widget('buttonBox')
def dialog_selectmodel_cancel(widget):
    if widget.isVisible():
        QTest.qWait(100)
        QTest.mouseClick(widget.button(QDialogButtonBox.Cancel), Qt.LeftButton)
        QTest.qWait(100)
    
@widget('action_preferences')
def dialog_preferences(action):
    action.trigger()
    QTest.qWait(200)
    return 'find_qobjects'
    
@widget('buttonBox')
def dialog_preferences_close(widget):
    if widget.isVisible():
        QTest.qWait(100)
        QTest.mouseClick(widget.button(QDialogButtonBox.Close), Qt.LeftButton)
        QTest.qWait(100)
        
#TODO: The testrunner can't currently test modal dialogs, this function will block
@widget('action_info')
def dialog_about(action):
    action.trigger()
    QTest.qWait(200)
    return 'find_qobjects'
    
@widget('buttonBox')
def dialog_about_close(widget):
    if widget.isVisible():
        QTest.qWait(100)
        QTest.mouseClick(widget.button(QDialogButtonBox.Close), Qt.LeftButton)
        QTest.qWait(100)
        


