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

#  Copyright © 2013-2015  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/>.


from PyQt5.QtCore import Qt, QPoint
from PyQt5.QtWidgets import QDialogButtonBox
from PyQt5.QtTest import QTest


field_functions = {
        # fieldname          objectname        default function
        '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.game.move_sequence.current_place),
        'game_len':         ('MainWindow', None, lambda widget: len(widget.game.move_sequence.moves)),
        'solved':           ('MainWindow', None, lambda widget: widget.game.current_state.is_solved()),
        'type':             ('MainWindow', None, lambda widget: widget.game.current_state.model.type),
        'sizes':            ('MainWindow', None, lambda widget: widget.game.current_state.model.sizes),
        'rotationx':        ('MainWindow', None, lambda widget: widget.cube_area.rotation_x),
        'rotationy':        ('MainWindow', None, lambda widget: widget.cube_area.rotation_y),
        'selection_mode':   ('MainWindow', None, lambda widget: widget.get_settings().draw.selection_nick),
        'mirror_faces':     ('MainWindow', None, lambda widget: widget.get_settings().draw.mirror_faces),
        '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: bool(widget.text())),
        'lblsize2':         ('label_heigth', None, lambda widget: bool(widget.text())),
        'lblsize3':         ('label_depth', None, lambda widget: bool(widget.text())),
        'size1':            ('spin_size1', None, lambda widget: (None if widget.isHidden() else widget.value())),
        'size2':            ('spin_size2', None, lambda widget: (None if widget.isHidden() else widget.value())),
        'size3':            ('spin_size3', None, lambda widget: (None if widget.isHidden() else widget.value())),
        '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()),
        'plugingroup':      ('MainWindow', None, lambda widget: widget.active_plugin_group),
    }

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('MainWindow')
def active_plugin_group_activate(widget, number, name=None):
    button = widget.plugin_group_widgets[number][0]
    if name is None or button.text() == _(name):
        QTest.mouseClick(button, Qt.LeftButton)
        
@widget('MainWindow')
def plugin_activate(widget, *names):
    treeview = widget.plugin_group_widgets[widget.active_plugin_group][1]
    model = widget.treestore
    index = treeview.rootIndex()
    names = [_(n) for n in names]
    assert names
    assert names[0] == index.data(), 'Wrong group: {!r} != {!r}'.format(names[0], index.data())
    for name in names[1:]:
        for row in range(model.rowCount(index)):
            _index = model.index(row, 0, index)
            if name == _index.data():
                index = _index
                break
        else:
            assert False, '{!r} in plugin {} not found'.format(name, names)
    treeview.scrollTo(index)
    rect = treeview.visualRect(index)
    assert rect.isValid()
    point = rect.center()
    treeview = widget.plugin_group_widgets[widget.active_plugin_group][1]
    QTest.mouseClick(treeview.viewport(), Qt.LeftButton, pos=point, delay=-1)
    QTest.mouseDClick(treeview.viewport(), Qt.LeftButton, pos=point, delay=-1)
    QTest.qWait(100)
    
@widget('MainWindow')
def set_settings_draw(widget, key, value):
    widget.get_settings().draw[key] = value
    QTest.qWait(100)
    
@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_move_(widget, x, y):
    QTest.mouseMove(widget, QPoint(x, y))
    QTest.qWait(1000)
    
@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('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('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)
        
@widget('MainWindow')
def direct_selectmodel(widget, mtype, size):
    widget.load_game(mtype, size)
    


