/****************************************************************************
**
** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:GPL-EXCEPT$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include <QtTest>
#include <QtGui/QWindow>
#include <QtGui/QCursor>
#include <QtGui/private/qguiapplication_p.h>

QT_BEGIN_NAMESPACE
namespace QTestPrivate {
extern Q_TESTLIB_EXPORT Qt::MouseButtons qtestMouseButtons; // from qtestcase.cpp
}
QT_END_NAMESPACE

class tst_Mouse : public QObject
{
    Q_OBJECT

private slots:
    void stateHandlingPart1_data();
    void stateHandlingPart1();
    void stateHandlingPart2();
    void deterministicEvents_data();
    void deterministicEvents();
};

class MouseWindow : public QWindow
{
public:
    Qt::MouseButtons stateInMouseMove = Qt::NoButton;
    int moveCount = 0;
    int pressCount = 0;

protected:
    void mousePressEvent(QMouseEvent *)
    {
        pressCount++;
    }

    void mouseMoveEvent(QMouseEvent *e)
    {
        moveCount++;
        stateInMouseMove = e->buttons();
    }
};

void tst_Mouse::stateHandlingPart1_data()
{
    QTest::addColumn<bool>("dummy");
    QTest::newRow("dummy-1") << true;
    QTest::newRow("dummy-2") << true;
}

void tst_Mouse::stateHandlingPart1()
{
    QFETCH(bool, dummy);
    Q_UNUSED(dummy);

    QWindow w;
    w.setFlags(w.flags() | Qt::FramelessWindowHint); // ### FIXME: QTBUG-63542
    w.show();
    w.setGeometry(100, 100, 200, 200);
    QVERIFY(QTest::qWaitForWindowActive(&w));

    QPoint point(10, 10);
    QPoint step(1, 1);

    // verify that we have a clean state after the previous data set
    QCOMPARE(QTestPrivate::qtestMouseButtons, Qt::NoButton);

    QTest::mousePress(&w, Qt::LeftButton, 0, point);
    QCOMPARE(QTestPrivate::qtestMouseButtons, Qt::LeftButton);
    QTest::mousePress(&w, Qt::RightButton, 0, point);
    QCOMPARE(QTestPrivate::qtestMouseButtons, Qt::LeftButton | Qt::RightButton);
    QTest::mouseMove(&w, point += step);
    QCOMPARE(QTestPrivate::qtestMouseButtons, Qt::LeftButton | Qt::RightButton);
    QTest::mouseRelease(&w, Qt::LeftButton, 0, point);
    QCOMPARE(QTestPrivate::qtestMouseButtons, Qt::RightButton);
    QTest::mouseMove(&w, point += step);
    QCOMPARE(QTestPrivate::qtestMouseButtons, Qt::RightButton);
    // test invalid input - left button was already released
    QTest::mouseRelease(&w, Qt::LeftButton, 0, point += point);
    QCOMPARE(QTestPrivate::qtestMouseButtons, Qt::RightButton);
    // test invalid input - right button is already pressed
    QTest::mousePress(&w, Qt::RightButton, 0, point);
    QCOMPARE(QTestPrivate::qtestMouseButtons, Qt::RightButton);
    // now continue with valid input
    QTest::mouseRelease(&w, Qt::RightButton, 0, point += point);
    QCOMPARE(QTestPrivate::qtestMouseButtons, Qt::NoButton);
    QTest::mouseMove(&w, point += step);
    QCOMPARE(QTestPrivate::qtestMouseButtons, Qt::NoButton);

    // exit this test function with some button in a pressed state
    QTest::mousePress(&w, Qt::LeftButton, 0, point);
    QTest::mousePress(&w, Qt::RightButton, 0, point);
    QCOMPARE(QTestPrivate::qtestMouseButtons, Qt::LeftButton | Qt::RightButton);
}

void tst_Mouse::stateHandlingPart2()
{
    MouseWindow w;
    w.setFlags(w.flags() | Qt::FramelessWindowHint); // ### FIXME: QTBUG-63542
    w.show();
    w.setGeometry(100, 100, 200, 200);
    QVERIFY(QTest::qWaitForWindowActive(&w));

    // verify that we have a clean state after stateHandlingPart1()
    QCOMPARE(QTestPrivate::qtestMouseButtons, Qt::NoButton);

#if !QT_CONFIG(cursor)
    QSKIP("This part of the test requires the QCursor API");
#else
    // The windowing system's view on a current button state might be different
    // from the qtestlib's mouse button state. This test verifies that the mouse
    // events generated by the system are adjusted to reflect qtestlib's view
    // on the current button state.
    // SKIP: not convinced yet that there is a valid use case for this.

    QSKIP("Not implemented beyond this point!");

    QPoint point(40, 40);
    QTest::mousePress(&w, Qt::LeftButton, 0, point);
    QTest::mousePress(&w, Qt::RightButton, 0, point);
    QCOMPARE(QTestPrivate::qtestMouseButtons, Qt::LeftButton | Qt::RightButton);
    w.moveCount = 0;
    // The windowing system will send mouse events with no buttons set
    QPoint moveToPoint = w.mapToGlobal(point + QPoint(1, 1));
    if (QCursor::pos() == moveToPoint)
        moveToPoint += QPoint(1, 1);
    QCursor::setPos(moveToPoint);
    QTRY_COMPARE(w.moveCount, 1);
    // Verify that qtestlib adjusted the button state
    QCOMPARE(w.stateInMouseMove, Qt::LeftButton | Qt::RightButton);
#endif
}

void tst_Mouse::deterministicEvents_data()
{
    QTest::addColumn<bool>("firstRun");
    QTest::newRow("first-run-true") << true;
    QTest::newRow("first-run-false") << false;
}

void tst_Mouse::deterministicEvents()
{
    /* QGuiApplication uses QGuiApplicationPrivate::lastCursorPosition to
    determine if it needs to generate an additional mouse move event for
    mouse press/release. Verify that this property is reset to it's default
    value, ensuring deterministic event generation behavior. Not resetting
    this value might affect event generation for subsequent tests runs (in
    unlikely case where a subsquent test does a mouse press in a pos that is
    equal to QGuiApplicationPrivate::lastCursorPosition, not causing mouse
    move to be generated.
    NOTE: running this test alone as in "./mouse deterministicEvents:first-run-false"
    won't test what this test is designed to test. */

    QSKIP("Not implemented!");

    /* It is undecided how and at what scope we want to handle reseting
    lastCursorPosition, or perhaps Qt should not be generating mouse move
    events as documented in QGuiApplicationPrivate::processMouseEvent(),
    then the problem would go away - ### Qt6 ? */

    QVERIFY(qIsInf(QGuiApplicationPrivate::lastCursorPosition.x()));
    QVERIFY(qIsInf(QGuiApplicationPrivate::lastCursorPosition.y()));

    QFETCH(bool, firstRun);

    MouseWindow w;
    w.setFlags(w.flags() | Qt::FramelessWindowHint); // ### FIXME: QTBUG-63542
    w.show();
    w.setGeometry(100, 100, 200, 200);
    QVERIFY(QTest::qWaitForWindowActive(&w));

    QCOMPARE(w.pressCount, 0);
    QCOMPARE(w.moveCount, 0);
    static QPoint m_cachedLastCursorPosition;
    if (firstRun) {
        QTest::mousePress(&w, Qt::LeftButton, 0, QPoint(40, 40));
        m_cachedLastCursorPosition = QGuiApplicationPrivate::lastCursorPosition.toPoint();
    } else {
        QPoint point = w.mapFromGlobal(m_cachedLastCursorPosition);
        QTest::mousePress(&w, Qt::LeftButton, 0, point);
    }
    QCOMPARE(w.pressCount, 1);
    QCOMPARE(w.moveCount, 1);
}

QTEST_MAIN(tst_Mouse)
#include "tst_mouse.moc"
