/****************************************************************************
**
** Copyright (C) 2016 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 "controllerwidget.h"
#include <controls.h>

#include <QtWidgets>
#include <QWindow>
#include <QBackingStore>
#include <QPaintDevice>
#include <QPainter>
#include <QRandomGenerator>
#include <QResizeEvent>

CoordinateControl::CoordinateControl(const QString &sep) : m_x(new QSpinBox), m_y(new QSpinBox)
{
    m_x->setMinimum(-2000);
    m_x->setMaximum(2000);
    connect(m_x, SIGNAL(valueChanged(int)), this, SLOT(spinBoxChanged()));
    m_y->setMinimum(-2000);
    m_y->setMaximum(2000);
    connect(m_y, SIGNAL(valueChanged(int)), this, SLOT(spinBoxChanged()));
    QHBoxLayout *l = new QHBoxLayout(this);
    l->setSpacing(2);
    l->addWidget(m_x);
    l->addWidget(new QLabel(sep));
    l->addWidget(m_y);
}

void CoordinateControl::setCoordinates(int x, int y)
{
    m_x->blockSignals(true);
    m_y->blockSignals(true);
    m_x->setValue(x);
    m_y->setValue(y);
    m_x->blockSignals(false);
    m_y->blockSignals(false);
}

QPair<int, int> CoordinateControl::coordinates() const
{
    return QPair<int, int>(m_x->value(), m_y->value());
}

void CoordinateControl::spinBoxChanged()
{
    const int x = m_x->value();
    const int y = m_y->value();
    emit pointValueChanged(QPoint(x, y));
    emit sizeValueChanged(QSize(x, y));
}

RectControl::RectControl()
    : m_point(new CoordinateControl(QLatin1String("+")))
    , m_size(new CoordinateControl(QLatin1String("x")))
{
    QHBoxLayout *l = new QHBoxLayout(this);
    l->setSpacing(0);
    l->setMargin(ControlLayoutMargin);
    connect(m_point, SIGNAL(pointValueChanged(QPoint)), this, SLOT(handleChanged()));
    connect(m_point, SIGNAL(pointValueChanged(QPoint)), this, SIGNAL(positionChanged(QPoint)));
    l->addWidget(m_point);
    l->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::MinimumExpanding, QSizePolicy::Ignored));
    connect(m_size, SIGNAL(sizeValueChanged(QSize)), this, SLOT(handleChanged()));
    connect(m_size, SIGNAL(sizeValueChanged(QSize)), this, SIGNAL(sizeChanged(QSize)));
    l->addWidget(m_size);
}

void RectControl::setRectValue(const QRect &r)
{
    m_point->setPointValue(r.topLeft());
    m_size->setSizeValue(r.size());
}

QRect RectControl::rectValue() const
{
    return QRect(m_point->pointValue(), m_size->sizeValue());
}

void RectControl::handleChanged()
{
    emit changed(rectValue());
}

BaseWindowControl::BaseWindowControl(QObject *w)
    : m_layout(new QGridLayout(this))
    , m_object(w)
    , m_geometry(new RectControl)
    , m_framePosition(new CoordinateControl(QLatin1String("x")))
    , m_moveEventLabel(new QLabel(tr("Move events")))
    , m_resizeEventLabel(new QLabel(tr("Resize events")))
    , m_mouseEventLabel(new QLabel(tr("Mouse events")))
    , m_moveCount(0)
    , m_resizeCount(0)
{
    m_object->installEventFilter(this);
    m_geometry->setTitle(tr("Geometry"));
    int row = 0;
    m_layout->addWidget(m_geometry, row, 0, 1, 2);
    m_layout->setMargin(ControlLayoutMargin);
    QGroupBox *frameGB = new QGroupBox(tr("Frame"));
    QVBoxLayout *frameL = new QVBoxLayout(frameGB);
    frameL->setSpacing(0);
    frameL->setMargin(ControlLayoutMargin);
    frameL->addWidget(m_framePosition);
    m_layout->addWidget(frameGB, row, 2);

    QGroupBox *eventGroupBox = new QGroupBox(tr("Events"));
    QVBoxLayout *l = new QVBoxLayout(eventGroupBox);
    l->setSpacing(0);
    l->setMargin(ControlLayoutMargin);
    l->addWidget(m_moveEventLabel);
    l->addWidget(m_resizeEventLabel);
    l->addWidget(m_mouseEventLabel);
    m_layout->addWidget(eventGroupBox, ++row, 2);

    connect(m_geometry, SIGNAL(positionChanged(QPoint)), this, SLOT(posChanged(QPoint)));
    connect(m_geometry, SIGNAL(sizeChanged(QSize)), this, SLOT(sizeChanged(QSize)));
    connect(m_framePosition, SIGNAL(pointValueChanged(QPoint)), this, SLOT(framePosChanged(QPoint)));
}

bool BaseWindowControl::eventFilter(QObject *, QEvent *e)
{
    switch (e->type()) {
    case QEvent::Resize: {
        const QResizeEvent *re = static_cast<const QResizeEvent *>(e);
        m_resizeEventLabel->setText(tr("Resize %1x%2 (#%3)")
                                    .arg(re->size().width()).arg(re->size().height())
                                    .arg(++m_resizeCount));
        refresh();
    }
        break;
    case QEvent::Move: {
        const QMoveEvent *me = static_cast<const QMoveEvent *>(e);
        m_moveEventLabel->setText(tr("Move %1,%2 (#%3)")
                                  .arg(me->pos().x()).arg(me->pos().y())
                                  .arg(++m_moveCount));
        refresh();
    }
        break;
    case QEvent::MouseMove: {
        const QMouseEvent *me = static_cast<const QMouseEvent *>(e);
        const QPoint pos = me->pos();
        QPoint globalPos = objectMapToGlobal(m_object, pos);
        m_mouseEventLabel->setText(tr("Mouse: %1,%2 Global: %3,%4 ").
                                   arg(pos.x()).arg(pos.y()).arg(globalPos.x()).arg(globalPos.y()));
    }
        break;
    case QEvent::WindowStateChange:
        refresh();
    default:
        break;
    }
    return false;
}

void BaseWindowControl::posChanged(const QPoint &p)
{
    QRect geom = objectGeometry(m_object);
    geom.moveTopLeft(p);
    setObjectGeometry(m_object, geom);
}

void BaseWindowControl::sizeChanged(const QSize &s)
{
    QRect geom = objectGeometry(m_object);
    geom.setSize(s);
    setObjectGeometry(m_object, geom);
}

void BaseWindowControl::framePosChanged(const QPoint &p)
{
    setObjectFramePosition(m_object, p);
}

void BaseWindowControl::refresh()
{
    m_geometry->setRectValue(objectGeometry(m_object));
    m_framePosition->setPointValue(objectFramePosition(m_object));
}

// A control for a QWidget
class WidgetWindowControl : public BaseWindowControl
{
    Q_OBJECT
public:
    explicit WidgetWindowControl(QWidget *w);

    virtual void refresh();

private slots:
    void statesChanged();

private:
    virtual QRect objectGeometry(const QObject *o) const
        { return static_cast<const QWidget *>(o)->geometry(); }
    virtual void setObjectGeometry(QObject *o, const QRect &r) const
        { static_cast<QWidget *>(o)->setGeometry(r); }
    virtual QPoint objectFramePosition(const QObject *o) const
        { return static_cast<const QWidget *>(o)->pos(); }
    virtual void setObjectFramePosition(QObject *o, const QPoint &p) const
        { static_cast<QWidget *>(o)->move(p); }
    virtual QPoint objectMapToGlobal(const QObject *o, const QPoint &p) const
        { return static_cast<const QWidget *>(o)->mapToGlobal(p); }
    virtual Qt::WindowFlags objectWindowFlags(const QObject *o) const
        { return static_cast<const QWidget *>(o)->windowFlags(); }
    virtual void setObjectWindowFlags(QObject *o, Qt::WindowFlags f);

    WindowStatesControl *m_statesControl;
};

WidgetWindowControl::WidgetWindowControl(QWidget *w )
    : BaseWindowControl(w)
    , m_statesControl(new WindowStatesControl)
{
    setTitle(w->windowTitle());
    m_layout->addWidget(m_statesControl, 2, 0);
    connect(m_statesControl, SIGNAL(changed()), this, SLOT(statesChanged()));
}

void WidgetWindowControl::setObjectWindowFlags(QObject *o, Qt::WindowFlags f)
{
    QWidget *w = static_cast<QWidget *>(o);
    const bool visible = w->isVisible();
    w->setWindowFlags(f); // hides.
    if (visible)
        w->show();
}

void WidgetWindowControl::refresh()
{
    const QWidget *w = static_cast<const QWidget *>(m_object);
    m_statesControl->setVisibleValue(w->isVisible());
    m_statesControl->setStates(w->windowState());
    BaseWindowControl::refresh();
}

void WidgetWindowControl::statesChanged()
{
    QWidget *w = static_cast<QWidget *>(m_object);
    w->setVisible(m_statesControl->visibleValue());
    w->setWindowState(m_statesControl->states());
}

#if QT_VERSION >= 0x050000

// Test window drawing diagonal lines
class Window : public QWindow
{
public:
    explicit Window(QWindow *parent = 0)
        : QWindow(parent)
        , m_backingStore(new QBackingStore(this))
        , m_color(Qt::GlobalColor(QRandomGenerator::global()->bounded(18)))
    {
        setObjectName(QStringLiteral("window"));
        setTitle(tr("TestWindow"));
        setProperty("_q_platform_MacUseNSWindow", QVariant(true));
    }

protected:
    void mouseMoveEvent(QMouseEvent * ev);
    void mousePressEvent(QMouseEvent * ev);
    void mouseReleaseEvent(QMouseEvent * e);
    void exposeEvent(QExposeEvent *)
        { render(); }

private:
    QBackingStore *m_backingStore;
    Qt::GlobalColor m_color;
    QPoint m_mouseDownPosition;
    void render();
};

void Window::mouseMoveEvent(QMouseEvent * ev)
{
    if (m_mouseDownPosition.isNull())
        return;

    QPoint delta = ev->pos() - m_mouseDownPosition;
    QPoint newPosition = position() + delta;
    setPosition(newPosition);
//    qDebug() << "diff" << delta << newPosition;
}

void Window::mousePressEvent(QMouseEvent * ev)
{
    m_mouseDownPosition = ev->pos();
}

void Window::mouseReleaseEvent(QMouseEvent *)
{
    m_mouseDownPosition = QPoint();
}

void Window::render()
{
    QRect rect(QPoint(), geometry().size());
    m_backingStore->resize(rect.size());
    m_backingStore->beginPaint(rect);
    if (!rect.size().isEmpty()) {
        QPaintDevice *device = m_backingStore->paintDevice();
        QPainter p(device);
        p.fillRect(rect, m_color);
        p.drawLine(0, 0, rect.width(), rect.height());
        p.drawLine(0, rect.height(), rect.width(), 0);
    }
    m_backingStore->endPaint();
    m_backingStore->flush(rect);
}

// A control for a QWindow
class WindowControl : public BaseWindowControl
{
    Q_OBJECT
public:
    explicit WindowControl(QWindow *w);

    virtual void refresh();

private slots:
    void showWindow();
    void hideWindow();
    void raiseWindow();
    void lowerWindow();
    void toggleAttachWindow();
    void addChildWindow();
private:
    virtual QRect objectGeometry(const QObject *o) const
        { return static_cast<const QWindow *>(o)->geometry(); }
    virtual void setObjectGeometry(QObject *o, const QRect &r) const
        { static_cast<QWindow *>(o)->setGeometry(r); }
    virtual QPoint objectFramePosition(const QObject *o) const
        { return static_cast<const QWindow *>(o)->framePosition(); }
    virtual void setObjectFramePosition(QObject *o, const QPoint &p) const
        { static_cast<QWindow *>(o)->setFramePosition(p); }
    virtual QPoint objectMapToGlobal(const QObject *o, const QPoint &p) const
        { return static_cast<const QWindow *>(o)->mapToGlobal(p); }
    virtual void setObjectWindowFlags(QObject *o, Qt::WindowFlags f)
        { static_cast<QWindow *>(o)->setFlags(f); }

    WindowStatesControl *m_statesControl;
    QWindow *m_window;
    QWindow *m_detachedParent; // set when this window is detached. This is the window we should re-attach to.
};

WindowControl::WindowControl(QWindow *w )
    : BaseWindowControl(w)
    , m_statesControl(new WindowStatesControl)
    , m_window(w)
    , m_detachedParent(0)
{
    setTitle(w->title());

    QPushButton *button = new QPushButton("Show Window");
    connect(button, SIGNAL(clicked()), SLOT(showWindow()));
    m_layout->addWidget(button, 1, 0);

    button = new QPushButton("hide Window");
    connect(button, SIGNAL(clicked()), SLOT(hideWindow()));
    m_layout->addWidget(button, 1, 1);

    button = new QPushButton("Rase Window");
    connect(button, SIGNAL(clicked()), SLOT(raiseWindow()));
    m_layout->addWidget(button, 2, 0);

    button = new QPushButton("Lower Window");
    connect(button, SIGNAL(clicked()), SLOT(lowerWindow()));
    m_layout->addWidget(button, 2, 1);

    button = new QPushButton("Toggle attach");
    connect(button, SIGNAL(clicked()), SLOT(toggleAttachWindow()));
    m_layout->addWidget(button, 3, 0);

    button = new QPushButton("Add Child Window");
    connect(button, SIGNAL(clicked()), SLOT(addChildWindow()));
    m_layout->addWidget(button, 3, 1);
}

void WindowControl::refresh()
{
    BaseWindowControl::refresh();
}

void WindowControl::showWindow()
{
    m_window->show();
}

void WindowControl::hideWindow()
{
    m_window->hide();
}

void WindowControl::raiseWindow()
{
    m_window->raise();
}

void WindowControl::lowerWindow()
{
    m_window->lower();
}

void WindowControl::toggleAttachWindow()
{
    if (m_detachedParent) {
        m_window->hide();
        m_window->setParent(m_detachedParent);
        m_window->show();
        m_detachedParent = 0;
    } else {
        m_detachedParent = m_window->parent();
        m_window->hide();
        m_window->setParent(0);
        m_window->show();
    }
}

void WindowControl::addChildWindow()
{
    qDebug() << "WindowControl::addChildWindow";
    Window *childWindow = new Window(m_window);

    QRect childGeometry(50, 50, 40, 40);
    childWindow->setGeometry(childGeometry);
    WindowControl *control = new WindowControl(childWindow);
    control->show();
}

#endif

ControllerWidget::ControllerWidget(QWidget *parent)
    : QMainWindow(parent)
    , m_testWindow(new Window)
{
    QMenu *fileMenu = menuBar()->addMenu(tr("File"));
    QAction *exitAction = fileMenu->addAction(tr("Exit"));
    exitAction->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_Q));
    connect(exitAction, SIGNAL(triggered()), qApp, SLOT(closeAllWindows()));

    QString title = QLatin1String("Child Window Geometry test, (Qt ");
    title += QLatin1String(QT_VERSION_STR);
    title += QLatin1String(", ");
    title += qApp->platformName();
    title += QLatin1Char(')');
    setWindowTitle(title);

    int x = 100;
    int y = 100;
    const QStringList args = QApplication::arguments();
    const int offsetArgIndex = args.indexOf(QLatin1String("-offset"));
    if (offsetArgIndex >=0 && offsetArgIndex < args.size() - 1) {
        y += args.at(offsetArgIndex + 1).toInt();
    } else {
        if (QT_VERSION < 0x050000)
            y += 400;
    }

    move(x, y);

    x += 800;

    x += 300;
    m_testWindow->setFlags(Qt::Window | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint
                                 | Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint
                                 | Qt::WindowTitleHint | Qt::WindowFullscreenButtonHint);
    m_testWindow->setFramePosition(QPoint(x, y));
    m_testWindow->resize(200, 200);
    m_testWindow->setTitle(tr("TestWindow"));

    QWidget *central = new QWidget ;
    QVBoxLayout *l = new QVBoxLayout(central);

    const QString labelText = tr(
        "<html><head/><body><p>This example lets you control the geometry"
        " of QWindows and child QWindows");

    l->addWidget(new QLabel(labelText));

    WindowControl *windowControl = new WindowControl(m_testWindow.data());
    l->addWidget(windowControl);

    setCentralWidget(central);
}

ControllerWidget::~ControllerWidget()
{


}

#include "controllerwidget.moc"
