/*
 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
 * Copyright (C) 2009 Torch Mobile Inc. http://www.torchmobile.com/
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1.  Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 * 2.  Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
 *     its contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
#include "config.h"
#include "EventSenderQt.h"

#include <QGraphicsSceneMouseEvent>
#include <QtTest/QtTest>

#define KEYCODE_DEL         127
#define KEYCODE_BACKSPACE   8
#define KEYCODE_LEFTARROW   0xf702
#define KEYCODE_RIGHTARROW  0xf703
#define KEYCODE_UPARROW     0xf700
#define KEYCODE_DOWNARROW   0xf701

// Ports like Gtk and Windows expose a different approach for their zooming
// API if compared to Qt: they have specific methods for zooming in and out,
// as well as a settable zoom factor, while Qt has only a 'setZoomValue' method.
// Hence Qt DRT adopts a fixed zoom-factor (1.2) for compatibility.
#define ZOOM_STEP           1.2

#define DRT_MESSAGE_DONE (QEvent::User + 1)

struct DRTEventQueue {
    QEvent* m_event;
    int m_delay;
};

static DRTEventQueue eventQueue[1024];
static unsigned endOfQueue;
static unsigned startOfQueue;

EventSender::EventSender(QWebPage* parent)
    : QObject(parent)
{
    m_page = parent;
    m_mouseButtonPressed = false;
    m_drag = false;
    memset(eventQueue, 0, sizeof(eventQueue));
    endOfQueue = 0;
    startOfQueue = 0;
    m_eventLoop = 0;
    m_currentButton = 0;
    resetClickCount();
    m_page->view()->installEventFilter(this);
    // So that we can match Scrollbar::pixelsPerLineStep() in WheelEventQt.cpp and
    // pass fast/events/platform-wheelevent-in-scrolling-div.html
    QApplication::setWheelScrollLines(2);
}

void EventSender::mouseDown(int button)
{
    Qt::MouseButton mouseButton;
    switch (button) {
    case 0:
        mouseButton = Qt::LeftButton;
        break;
    case 1:
        mouseButton = Qt::MidButton;
        break;
    case 2:
        mouseButton = Qt::RightButton;
        break;
    case 3:
        // fast/events/mouse-click-events expects the 4th button to be treated as the middle button
        mouseButton = Qt::MidButton;
        break;
    default:
        mouseButton = Qt::LeftButton;
        break;
    }

    // only consider a click to count, an event originated by the
    // same previous button and at the same position.
    if (m_currentButton == button
        && m_mousePos == m_clickPos
        && m_clickTimer.isActive())
        m_clickCount++;
    else
        m_clickCount = 1;

    m_currentButton = button;
    m_clickPos = m_mousePos;
    m_mouseButtons |= mouseButton;

//     qDebug() << "EventSender::mouseDown" << frame;
    QEvent* event;
    if (isGraphicsBased()) {
        event = createGraphicsSceneMouseEvent((m_clickCount == 2) ?
                    QEvent::GraphicsSceneMouseDoubleClick : QEvent::GraphicsSceneMousePress,
                    m_mousePos, m_mousePos, mouseButton, m_mouseButtons, Qt::NoModifier);
    } else {
        event = new QMouseEvent((m_clickCount == 2) ? QEvent::MouseButtonDblClick :
                    QEvent::MouseButtonPress, m_mousePos, m_mousePos,
                    mouseButton, m_mouseButtons, Qt::NoModifier);
    }

    sendOrQueueEvent(event);

    m_clickTimer.start(QApplication::doubleClickInterval(), this);
}

void EventSender::mouseUp(int button)
{
    Qt::MouseButton mouseButton;
    switch (button) {
    case 0:
        mouseButton = Qt::LeftButton;
        break;
    case 1:
        mouseButton = Qt::MidButton;
        break;
    case 2:
        mouseButton = Qt::RightButton;
        break;
    case 3:
        // fast/events/mouse-click-events expects the 4th button to be treated as the middle button
        mouseButton = Qt::MidButton;
        break;
    default:
        mouseButton = Qt::LeftButton;
        break;
    }

    m_mouseButtons &= ~mouseButton;

//     qDebug() << "EventSender::mouseUp" << frame;
    QEvent* event;
    if (isGraphicsBased()) {
        event = createGraphicsSceneMouseEvent(QEvent::GraphicsSceneMouseRelease,
                    m_mousePos, m_mousePos, mouseButton, m_mouseButtons, Qt::NoModifier);
    } else {
        event = new QMouseEvent(QEvent::MouseButtonRelease,
                    m_mousePos, m_mousePos, mouseButton, m_mouseButtons, Qt::NoModifier);
    }

    sendOrQueueEvent(event);
}

void EventSender::mouseMoveTo(int x, int y)
{
//     qDebug() << "EventSender::mouseMoveTo" << x << y;
    m_mousePos = QPoint(x, y);

    QEvent* event;
    if (isGraphicsBased()) {
        event = createGraphicsSceneMouseEvent(QEvent::GraphicsSceneMouseMove,
                    m_mousePos, m_mousePos, Qt::NoButton, m_mouseButtons, Qt::NoModifier);
    } else {
        event = new QMouseEvent(QEvent::MouseMove,
                    m_mousePos, m_mousePos, Qt::NoButton, m_mouseButtons, Qt::NoModifier);
    }

    sendOrQueueEvent(event);
}

#ifndef QT_NO_WHEELEVENT
void EventSender::mouseScrollBy(int x, int y)
{
    continuousMouseScrollBy((x*120), (y*120));
}

void EventSender::continuousMouseScrollBy(int x, int y)
{
    // continuousMouseScrollBy() mimics devices that send fine-grained scroll events where the 'delta' specified is not the usual
    // multiple of 120. See http://doc.qt.nokia.com/4.6/qwheelevent.html#delta for a good explanation of this.
    if (x) {
        QEvent* event;
        if (isGraphicsBased()) {
            event = createGraphicsSceneWheelEvent(QEvent::GraphicsSceneWheel,
                        m_mousePos, m_mousePos, x, Qt::NoModifier, Qt::Horizontal);
        } else
            event = new QWheelEvent(m_mousePos, m_mousePos, x, m_mouseButtons, Qt::NoModifier, Qt::Horizontal);

        sendOrQueueEvent(event);
    }
    if (y) {
        QEvent* event;
        if (isGraphicsBased()) {
            event = createGraphicsSceneWheelEvent(QEvent::GraphicsSceneWheel,
                        m_mousePos, m_mousePos, y, Qt::NoModifier, Qt::Vertical);
        } else
            event = new QWheelEvent(m_mousePos, m_mousePos, y, m_mouseButtons, Qt::NoModifier, Qt::Vertical);

        sendOrQueueEvent(event);
    }
}
#endif

void EventSender::leapForward(int ms)
{
    eventQueue[endOfQueue].m_delay = ms;
    //qDebug() << "EventSender::leapForward" << ms;
}

void EventSender::keyDown(const QString& string, const QStringList& modifiers, unsigned int location)
{
    QString s = string;
    Qt::KeyboardModifiers modifs = 0;
    for (int i = 0; i < modifiers.size(); ++i) {
        const QString& m = modifiers.at(i);
        if (m == "ctrlKey")
            modifs |= Qt::ControlModifier;
        else if (m == "shiftKey")
            modifs |= Qt::ShiftModifier;
        else if (m == "altKey")
            modifs |= Qt::AltModifier;
        else if (m == "metaKey")
            modifs |= Qt::MetaModifier;
    }
    if (location == 3)
        modifs |= Qt::KeypadModifier;
    int code = 0;
    if (string.length() == 1) {
        code = string.unicode()->unicode();
        //qDebug() << ">>>>>>>>> keyDown" << code << (char)code;
        // map special keycodes used by the tests to something that works for Qt/X11
        if (code == '\r') {
            code = Qt::Key_Return;
        } else if (code == '\t') {
            code = Qt::Key_Tab;
            if (modifs == Qt::ShiftModifier)
                code = Qt::Key_Backtab;
            s = QString();
        } else if (code == KEYCODE_DEL || code == KEYCODE_BACKSPACE) {
            code = Qt::Key_Backspace;
            if (modifs == Qt::AltModifier)
                modifs = Qt::ControlModifier;
            s = QString();
        } else if (code == 'o' && modifs == Qt::ControlModifier) {
            // Mimic the emacs ctrl-o binding on Mac by inserting a paragraph
            // separator and then putting the cursor back to its original
            // position. Allows us to pass emacs-ctrl-o.html
            s = QLatin1String("\n");
            code = '\n';
            modifs = 0;
            QKeyEvent event(QEvent::KeyPress, code, modifs, s);
            sendEvent(m_page, &event);
            QKeyEvent event2(QEvent::KeyRelease, code, modifs, s);
            sendEvent(m_page, &event2);
            s = QString();
            code = Qt::Key_Left;
        } else if (code == 'y' && modifs == Qt::ControlModifier) {
            s = QLatin1String("c");
            code = 'c';
        } else if (code == 'k' && modifs == Qt::ControlModifier) {
            s = QLatin1String("x");
            code = 'x';
        } else if (code == 'a' && modifs == Qt::ControlModifier) {
            s = QString();
            code = Qt::Key_Home;
            modifs = 0;
        } else if (code == KEYCODE_LEFTARROW) {
            s = QString();
            code = Qt::Key_Left;
            if (modifs & Qt::MetaModifier) {
                code = Qt::Key_Home;
                modifs &= ~Qt::MetaModifier;
            }
        } else if (code == KEYCODE_RIGHTARROW) {
            s = QString();
            code = Qt::Key_Right;
            if (modifs & Qt::MetaModifier) {
                code = Qt::Key_End;
                modifs &= ~Qt::MetaModifier;
            }
        } else if (code == KEYCODE_UPARROW) {
            s = QString();
            code = Qt::Key_Up;
            if (modifs & Qt::MetaModifier) {
                code = Qt::Key_PageUp;
                modifs &= ~Qt::MetaModifier;
            }
        } else if (code == KEYCODE_DOWNARROW) {
            s = QString();
            code = Qt::Key_Down;
            if (modifs & Qt::MetaModifier) {
                code = Qt::Key_PageDown;
                modifs &= ~Qt::MetaModifier;
            }
        } else if (code == 'a' && modifs == Qt::ControlModifier) {
            s = QString();
            code = Qt::Key_Home;
            modifs = 0;
        } else
            code = string.unicode()->toUpper().unicode();
    } else {
        //qDebug() << ">>>>>>>>> keyDown" << string;

        if (string.startsWith(QLatin1Char('F')) && string.count() <= 3) {
            s = s.mid(1);
            int functionKey = s.toInt();
            Q_ASSERT(functionKey >= 1 && functionKey <= 35);
            code = Qt::Key_F1 + (functionKey - 1);
        // map special keycode strings used by the tests to something that works for Qt/X11
        } else if (string == QLatin1String("leftArrow")) {
            s = QString();
            code = Qt::Key_Left;
        } else if (string == QLatin1String("rightArrow")) {
            s = QString();
            code = Qt::Key_Right;
        } else if (string == QLatin1String("upArrow")) {
            s = QString();
            code = Qt::Key_Up;
        } else if (string == QLatin1String("downArrow")) {
            s = QString();
            code = Qt::Key_Down;
        } else if (string == QLatin1String("pageUp")) {
            s = QString();
            code = Qt::Key_PageUp;
        } else if (string == QLatin1String("pageDown")) {
            s = QString();
            code = Qt::Key_PageDown;
        } else if (string == QLatin1String("home")) {
            s = QString();
            code = Qt::Key_Home;
        } else if (string == QLatin1String("end")) {
            s = QString();
            code = Qt::Key_End;
        } else if (string == QLatin1String("insert")) {
            s = QString();
            code = Qt::Key_Insert;
        } else if (string == QLatin1String("delete")) {
            s = QString();
            code = Qt::Key_Delete;
        } else if (string == QLatin1String("printScreen")) {
            s = QString();
            code = Qt::Key_Print;
        } else if (string == QLatin1String("menu")) {
            s = QString();
            code = Qt::Key_Menu;
        }
    }
    QKeyEvent event(QEvent::KeyPress, code, modifs, s);
    sendEvent(m_page, &event);
    QKeyEvent event2(QEvent::KeyRelease, code, modifs, s);
    sendEvent(m_page, &event2);
}

QStringList EventSender::contextClick()
{
    QMouseEvent event(QEvent::MouseButtonPress, m_mousePos, Qt::RightButton, Qt::RightButton, Qt::NoModifier);
    sendEvent(m_page, &event);
    QMouseEvent event2(QEvent::MouseButtonRelease, m_mousePos, Qt::RightButton, Qt::RightButton, Qt::NoModifier);
    sendEvent(m_page, &event2);

    if (isGraphicsBased()) {
        QGraphicsSceneContextMenuEvent ctxEvent(QEvent::GraphicsSceneContextMenu);
        ctxEvent.setReason(QGraphicsSceneContextMenuEvent::Mouse);
        ctxEvent.setPos(m_mousePos);
        WebCore::WebViewGraphicsBased* view = qobject_cast<WebCore::WebViewGraphicsBased*>(m_page->view());
        if (view)
            sendEvent(view->graphicsView(), &ctxEvent);
    } else {
        QContextMenuEvent ctxEvent(QContextMenuEvent::Mouse, m_mousePos);
        sendEvent(m_page->view(), &ctxEvent);
    }
    return DumpRenderTreeSupportQt::contextMenu(m_page);
}

void EventSender::scheduleAsynchronousClick()
{
    QMouseEvent* event = new QMouseEvent(QEvent::MouseButtonPress, m_mousePos, Qt::LeftButton, Qt::RightButton, Qt::NoModifier);
    postEvent(m_page, event);
    QMouseEvent* event2 = new QMouseEvent(QEvent::MouseButtonRelease, m_mousePos, Qt::LeftButton, Qt::RightButton, Qt::NoModifier);
    postEvent(m_page, event2);
}

void EventSender::addTouchPoint(int x, int y)
{
    // Use index to refer to the position in the vector that this touch
    // is stored. We then create a unique id for the touch that will be
    // passed into WebCore.
    int index = m_touchPoints.count();
    int id = m_touchPoints.isEmpty() ? 0 : m_touchPoints.last().id() + 1;
    QTouchEvent::TouchPoint point(id);
    m_touchPoints.append(point);
    updateTouchPoint(index, x, y);
    m_touchPoints[index].setState(Qt::TouchPointPressed);
}

void EventSender::updateTouchPoint(int index, int x, int y)
{
    if (index < 0 || index >= m_touchPoints.count())
        return;

    QTouchEvent::TouchPoint &p = m_touchPoints[index];
    p.setPos(QPointF(x, y));
    p.setState(Qt::TouchPointMoved);
}

void EventSender::setTouchModifier(const QString &modifier, bool enable)
{
    Qt::KeyboardModifier mod = Qt::NoModifier;
    if (!modifier.compare(QLatin1String("shift"), Qt::CaseInsensitive))
        mod = Qt::ShiftModifier;
    else if (!modifier.compare(QLatin1String("alt"), Qt::CaseInsensitive))
        mod = Qt::AltModifier;
    else if (!modifier.compare(QLatin1String("meta"), Qt::CaseInsensitive))
        mod = Qt::MetaModifier;
    else if (!modifier.compare(QLatin1String("ctrl"), Qt::CaseInsensitive))
        mod = Qt::ControlModifier;

    if (enable)
        m_touchModifiers |= mod;
    else
        m_touchModifiers &= ~mod;
}

void EventSender::touchStart()
{
    if (!m_touchActive) {
        sendTouchEvent(QEvent::TouchBegin);
        m_touchActive = true;
    } else
        sendTouchEvent(QEvent::TouchUpdate);
}

void EventSender::touchMove()
{
    sendTouchEvent(QEvent::TouchUpdate);
}

void EventSender::touchEnd()
{
    for (int i = 0; i < m_touchPoints.count(); ++i)
        if (m_touchPoints[i].state() != Qt::TouchPointReleased) {
            sendTouchEvent(QEvent::TouchUpdate);
            return;
        }
    sendTouchEvent(QEvent::TouchEnd);
    m_touchActive = false;
}

void EventSender::clearTouchPoints()
{
    m_touchPoints.clear();
    m_touchModifiers = Qt::KeyboardModifiers();
    m_touchActive = false;
}

void EventSender::releaseTouchPoint(int index)
{
    if (index < 0 || index >= m_touchPoints.count())
        return;

    m_touchPoints[index].setState(Qt::TouchPointReleased);
}

void EventSender::sendTouchEvent(QEvent::Type type)
{
    QTouchEvent event(type, QTouchEvent::TouchScreen, m_touchModifiers);
    event.setTouchPoints(m_touchPoints);
    sendEvent(m_page, &event);
    QList<QTouchEvent::TouchPoint>::Iterator it = m_touchPoints.begin();
    while (it != m_touchPoints.end()) {
        if (it->state() == Qt::TouchPointReleased)
            it = m_touchPoints.erase(it);
        else {
            it->setState(Qt::TouchPointStationary);
            ++it;
        }
    }
}

void EventSender::zoomPageIn()
{
    if (QWebFrame* frame = m_page->mainFrame())
        frame->setZoomFactor(frame->zoomFactor() * ZOOM_STEP);
}

void EventSender::zoomPageOut()
{
    if (QWebFrame* frame = m_page->mainFrame())
        frame->setZoomFactor(frame->zoomFactor() / ZOOM_STEP);
}

void EventSender::textZoomIn()
{
    if (QWebFrame* frame = m_page->mainFrame())
        frame->setTextSizeMultiplier(frame->textSizeMultiplier() * ZOOM_STEP);
}

void EventSender::textZoomOut()
{
    if (QWebFrame* frame = m_page->mainFrame())
        frame->setTextSizeMultiplier(frame->textSizeMultiplier() / ZOOM_STEP);
}

QWebFrame* EventSender::frameUnderMouse() const
{
    QWebFrame* frame = m_page->mainFrame();

redo:
    QList<QWebFrame*> children = frame->childFrames();
    for (int i = 0; i < children.size(); ++i) {
        if (children.at(i)->geometry().contains(m_mousePos)) {
            frame = children.at(i);
            goto redo;
        }
    }
    if (frame->geometry().contains(m_mousePos))
        return frame;
    return 0;
}

void EventSender::sendOrQueueEvent(QEvent* event)
{
    // Mouse move events are queued if 
    // 1. A previous event was queued.
    // 2. A delay was set-up by leapForward().
    // 3. A call to mouseMoveTo while the mouse button is pressed could initiate a drag operation, and that does not return until mouseUp is processed. 
    // To be safe and avoid a deadlock, this event is queued.
    if (endOfQueue == startOfQueue && !eventQueue[endOfQueue].m_delay && (!(m_mouseButtonPressed && (m_eventLoop && event->type() == QEvent::MouseButtonRelease)))) {
        sendEvent(m_page->view(), event);
        delete event;
        return;
    }
    eventQueue[endOfQueue++].m_event = event;
    eventQueue[endOfQueue].m_delay = 0;
    replaySavedEvents(event->type() != QEvent::MouseMove);
}

void EventSender::replaySavedEvents(bool flush)
{
    if (startOfQueue < endOfQueue) {
        // First send all the events that are ready to be sent
        while (!eventQueue[startOfQueue].m_delay && startOfQueue < endOfQueue) {
            QEvent* ev = eventQueue[startOfQueue++].m_event;
            postEvent(m_page->view(), ev);
        }
        if (startOfQueue == endOfQueue) {
            // Reset the queue
            startOfQueue = 0;
            endOfQueue = 0;
        } else {
            QTest::qWait(eventQueue[startOfQueue].m_delay);
            eventQueue[startOfQueue].m_delay = 0;
        }
    }
    if (!flush)
        return;

    // Send a marker event, it will tell us when it is safe to exit the new event loop
    QEvent* drtEvent = new QEvent((QEvent::Type)DRT_MESSAGE_DONE);
    QApplication::postEvent(m_page->view(), drtEvent);

    // Start an event loop for async handling of Drag & Drop
    m_eventLoop = new QEventLoop;
    m_eventLoop->exec();
    delete m_eventLoop;
    m_eventLoop = 0;
}

bool EventSender::eventFilter(QObject* watched, QEvent* event)
{
    if (watched != m_page->view())
        return false;
    switch (event->type()) {
    case QEvent::Leave:
        return true;
    case QEvent::MouseButtonPress:
    case QEvent::GraphicsSceneMousePress:
        m_mouseButtonPressed = true;
        break;
    case QEvent::MouseMove:
    case QEvent::GraphicsSceneMouseMove:
        if (m_mouseButtonPressed)
            m_drag = true;
        break;
    case QEvent::MouseButtonRelease:
    case QEvent::GraphicsSceneMouseRelease:
        m_mouseButtonPressed = false;
        m_drag = false;
        break;
    case DRT_MESSAGE_DONE:
        m_eventLoop->exit();
        return true;
    }
    return false;
}

void EventSender::timerEvent(QTimerEvent* ev)
{
    m_clickTimer.stop();
}

QGraphicsSceneMouseEvent* EventSender::createGraphicsSceneMouseEvent(QEvent::Type type, const QPoint& pos, const QPoint& screenPos, Qt::MouseButton button, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers)
{
    QGraphicsSceneMouseEvent* event;
    event = new QGraphicsSceneMouseEvent(type);
    event->setPos(pos);
    event->setScreenPos(screenPos);
    event->setButton(button);
    event->setButtons(buttons);
    event->setModifiers(modifiers);

    return event;
}

QGraphicsSceneWheelEvent* EventSender::createGraphicsSceneWheelEvent(QEvent::Type type, const QPoint& pos, const QPoint& screenPos, int delta, Qt::KeyboardModifiers modifiers, Qt::Orientation orientation)
{
    QGraphicsSceneWheelEvent* event;
    event = new QGraphicsSceneWheelEvent(type);
    event->setPos(pos);
    event->setScreenPos(screenPos);
    event->setDelta(delta);
    event->setModifiers(modifiers);
    event->setOrientation(orientation);

    return event;
}

void EventSender::sendEvent(QObject* receiver, QEvent* event)
{
    if (WebCore::WebViewGraphicsBased* view = qobject_cast<WebCore::WebViewGraphicsBased*>(receiver))
        view->scene()->sendEvent(view->graphicsView(), event);
    else
        QApplication::sendEvent(receiver, event);
}

void EventSender::postEvent(QObject* receiver, QEvent* event)
{
    // QGraphicsScene does not have a postEvent method, so send the event in this case
    // and delete it after that.
    if (WebCore::WebViewGraphicsBased* view = qobject_cast<WebCore::WebViewGraphicsBased*>(receiver)) {
        view->scene()->sendEvent(view->graphicsView(), event);
        delete event;
    } else
        QApplication::postEvent(receiver, event); // event deleted by the system
}
