/*
 * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
 *
 * 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 "DumpRenderTree.h"
#include "EventSender.h"

#include "DraggingInfo.h"

#include <WebCore/COMPtr.h>
#include <wtf/ASCIICType.h>
#include <wtf/Platform.h>
#include <JavaScriptCore/JavaScriptCore.h>
#include <JavaScriptCore/Assertions.h>
#include <WebKit/IWebFrame.h>
#include <WebKit/IWebFramePrivate.h>
#include <windows.h>

#define WM_DRT_SEND_QUEUED_EVENT (WM_APP+1)

static bool down;
static bool dragMode = true;
static bool replayingSavedEvents;
static int timeOffset;
static POINT lastMousePosition;

struct DelayedMessage {
    MSG msg;
    unsigned delay;
};

static DelayedMessage msgQueue[1024];
static unsigned endOfQueue;
static unsigned startOfQueue;

static bool didDragEnter;
DraggingInfo* draggingInfo = 0;

static JSValueRef getDragModeCallback(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
{
    return JSValueMakeBoolean(context, dragMode);
}

static bool setDragModeCallback(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception)
{
    dragMode = JSValueToBoolean(context, value);
    return true;
}

static JSValueRef getConstantCallback(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
{
    if (JSStringIsEqualToUTF8CString(propertyName, "WM_KEYDOWN"))
        return JSValueMakeNumber(context, WM_KEYDOWN);
    if (JSStringIsEqualToUTF8CString(propertyName, "WM_KEYUP"))
        return JSValueMakeNumber(context, WM_KEYUP);
    if (JSStringIsEqualToUTF8CString(propertyName, "WM_CHAR"))
        return JSValueMakeNumber(context, WM_CHAR);
    if (JSStringIsEqualToUTF8CString(propertyName, "WM_DEADCHAR"))
        return JSValueMakeNumber(context, WM_DEADCHAR);
    if (JSStringIsEqualToUTF8CString(propertyName, "WM_SYSKEYDOWN"))
        return JSValueMakeNumber(context, WM_SYSKEYDOWN);
    if (JSStringIsEqualToUTF8CString(propertyName, "WM_SYSKEYUP"))
        return JSValueMakeNumber(context, WM_SYSKEYUP);
    if (JSStringIsEqualToUTF8CString(propertyName, "WM_SYSCHAR"))
        return JSValueMakeNumber(context, WM_SYSCHAR);
    if (JSStringIsEqualToUTF8CString(propertyName, "WM_SYSDEADCHAR"))
        return JSValueMakeNumber(context, WM_SYSDEADCHAR);
    ASSERT_NOT_REACHED();
    return JSValueMakeUndefined(context);
}

static JSValueRef leapForwardCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
{
    if (argumentCount > 0) {
        msgQueue[endOfQueue].delay = JSValueToNumber(context, arguments[0], exception);
        ASSERT(!exception || !*exception);
    }

    return JSValueMakeUndefined(context);
}

static DWORD currentEventTime()
{
    return ::GetTickCount() + timeOffset;
}

static MSG makeMsg(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    MSG result = {0};
    result.hwnd = hwnd;
    result.message = message;
    result.wParam = wParam;
    result.lParam = lParam;
    result.time = currentEventTime();
    result.pt = lastMousePosition;

    return result;
}

static LRESULT dispatchMessage(const MSG* msg)
{
    ASSERT(msg);
    ::TranslateMessage(msg);
    return ::DispatchMessage(msg);
}

static JSValueRef contextClickCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
{
    COMPtr<IWebFramePrivate> framePrivate;
    if (SUCCEEDED(frame->QueryInterface(&framePrivate)))
        framePrivate->layout();

    down = true;
    MSG msg = makeMsg(webViewWindow, WM_RBUTTONDOWN, 0, MAKELPARAM(lastMousePosition.x, lastMousePosition.y));
    dispatchMessage(&msg);
    down = false;
    msg = makeMsg(webViewWindow, WM_RBUTTONUP, 0, MAKELPARAM(lastMousePosition.x, lastMousePosition.y));
    dispatchMessage(&msg);
    
    return JSValueMakeUndefined(context);
}

static JSValueRef mouseDownCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
{
    COMPtr<IWebFramePrivate> framePrivate;
    if (SUCCEEDED(frame->QueryInterface(&framePrivate)))
        framePrivate->layout();

    down = true;
    MSG msg = makeMsg(webViewWindow, WM_LBUTTONDOWN, 0, MAKELPARAM(lastMousePosition.x, lastMousePosition.y));
    if (!msgQueue[endOfQueue].delay)
        dispatchMessage(&msg);
    else {
        // replaySavedEvents has the required logic to make leapForward delays work
        msgQueue[endOfQueue++].msg = msg;
        replaySavedEvents();
    }

    return JSValueMakeUndefined(context);
}

static inline POINTL pointl(const POINT& point)
{
    POINTL result;
    result.x = point.x;
    result.y = point.y;
    return result;
}

static void doMouseUp(MSG msg)
{
    COMPtr<IWebFramePrivate> framePrivate;
    if (SUCCEEDED(frame->QueryInterface(&framePrivate)))
        framePrivate->layout();

    dispatchMessage(&msg);
    down = false;

    if (draggingInfo) {
        COMPtr<IWebView> webView;
        COMPtr<IDropTarget> webViewDropTarget;
        if (SUCCEEDED(frame->webView(&webView)) && SUCCEEDED(webView->QueryInterface(IID_IDropTarget, (void**)&webViewDropTarget))) {
            POINT screenPoint = msg.pt;
            DWORD effect = 0;
            ::ClientToScreen(webViewWindow, &screenPoint);
            if (!didDragEnter) {
                webViewDropTarget->DragEnter(draggingInfo->dataObject(), 0, pointl(screenPoint), &effect);
                didDragEnter = true;
            }
            HRESULT hr = draggingInfo->dropSource()->QueryContinueDrag(0, 0);
            webViewDropTarget->DragOver(0, pointl(screenPoint), &effect);
            if (hr == DRAGDROP_S_DROP && effect != DROPEFFECT_NONE) {
                DWORD effect = 0;
                webViewDropTarget->Drop(draggingInfo->dataObject(), 0, pointl(screenPoint), &effect);
            } else
                webViewDropTarget->DragLeave();

            delete draggingInfo;
            draggingInfo = 0;
        }
    }
}

static JSValueRef mouseUpCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
{
    MSG msg = makeMsg(webViewWindow, WM_LBUTTONUP, 0, MAKELPARAM(lastMousePosition.x, lastMousePosition.y));

    if ((dragMode && !replayingSavedEvents) || msgQueue[endOfQueue].delay) {
        msgQueue[endOfQueue++].msg = msg;
        replaySavedEvents();
    } else
        doMouseUp(msg);

    return JSValueMakeUndefined(context);
}

static void doMouseMove(MSG msg)
{
    COMPtr<IWebFramePrivate> framePrivate;
    if (SUCCEEDED(frame->QueryInterface(&framePrivate)))
        framePrivate->layout();

    dispatchMessage(&msg);

    if (down && draggingInfo) {
        POINT screenPoint = msg.pt;
        ::ClientToScreen(webViewWindow, &screenPoint);

        IWebView* webView;
        COMPtr<IDropTarget> webViewDropTarget;
        if (SUCCEEDED(frame->webView(&webView)) && SUCCEEDED(webView->QueryInterface(IID_IDropTarget, (void**)&webViewDropTarget))) {
            DWORD effect = 0;
            if (didDragEnter)
                webViewDropTarget->DragOver(MK_LBUTTON, pointl(screenPoint), &effect);
            else {
                webViewDropTarget->DragEnter(draggingInfo->dataObject(), 0, pointl(screenPoint), &effect);
                didDragEnter = true;
            }
            draggingInfo->dropSource()->GiveFeedback(effect);
        }
    }
}

static JSValueRef mouseMoveToCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
{
    if (argumentCount < 2)
        return JSValueMakeUndefined(context);

    lastMousePosition.x = (int)JSValueToNumber(context, arguments[0], exception);
    ASSERT(!exception || !*exception);
    lastMousePosition.y = (int)JSValueToNumber(context, arguments[1], exception);
    ASSERT(!exception || !*exception);

    MSG msg = makeMsg(webViewWindow, WM_MOUSEMOVE, down ? MK_LBUTTON : 0, MAKELPARAM(lastMousePosition.x, lastMousePosition.y));

    if (dragMode && down && !replayingSavedEvents) {
        msgQueue[endOfQueue++].msg = msg;
        return JSValueMakeUndefined(context);
    }

    doMouseMove(msg);

    return JSValueMakeUndefined(context);
}

void replaySavedEvents()
{
    replayingSavedEvents = true;
  
    MSG msg = { 0 };

    while (startOfQueue < endOfQueue && !msgQueue[startOfQueue].delay) {
        msg = msgQueue[startOfQueue++].msg;
        switch (msg.message) {
            case WM_LBUTTONUP:
                doMouseUp(msg);
                break;
            case WM_MOUSEMOVE:
                doMouseMove(msg);
                break;
            case WM_LBUTTONDOWN:
                dispatchMessage(&msg);
                break;
            default:
                // Not reached
                break;
        }
    }

    int numQueuedMessages = endOfQueue - startOfQueue;
    if (!numQueuedMessages) {
        startOfQueue = 0;
        endOfQueue = 0;
        replayingSavedEvents = false;
        ASSERT(!down);
        return;
    }

    if (msgQueue[startOfQueue].delay) {
        ::Sleep(msgQueue[startOfQueue].delay);
        msgQueue[startOfQueue].delay = 0;
    }

    ::PostMessage(webViewWindow, WM_DRT_SEND_QUEUED_EVENT, 0, 0);
    while (::GetMessage(&msg, webViewWindow, 0, 0)) {
        // FIXME: Why do we get a WM_MOUSELEAVE? it breaks tests
        if (msg.message == WM_MOUSELEAVE)
            continue;
        if (msg.message != WM_DRT_SEND_QUEUED_EVENT) {
            dispatchMessage(&msg);
            continue;
        }
        msg = msgQueue[startOfQueue++].msg;
        switch (msg.message) {
            case WM_LBUTTONUP:
                doMouseUp(msg);
                break;
            case WM_MOUSEMOVE:
                doMouseMove(msg);
                break;
            case WM_LBUTTONDOWN:
                dispatchMessage(&msg);
                break;
            default:
                // Not reached
                break;
        }
        if (startOfQueue >= endOfQueue)
            break;
        ::Sleep(msgQueue[startOfQueue].delay);
        msgQueue[startOfQueue].delay = 0;
        ::PostMessage(webViewWindow, WM_DRT_SEND_QUEUED_EVENT, 0, 0);
    }
    startOfQueue = 0;
    endOfQueue = 0;

    replayingSavedEvents = false;
}

static JSValueRef keyDownCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
{
    if (argumentCount < 1)
        return JSValueMakeUndefined(context);

    static const JSStringRef lengthProperty = JSStringCreateWithUTF8CString("length");

    COMPtr<IWebFramePrivate> framePrivate;
    if (SUCCEEDED(frame->QueryInterface(&framePrivate)))
        framePrivate->layout();
    
    JSStringRef character = JSValueToStringCopy(context, arguments[0], exception);
    ASSERT(!*exception);
    int virtualKeyCode;
    int charCode = 0;
    int keyData = 1;
    bool needsShiftKeyModifier = false;
    if (JSStringIsEqualToUTF8CString(character, "leftArrow")) {
        virtualKeyCode = VK_LEFT;
        keyData += KF_EXTENDED << 16; // In this case, extended means "not keypad".
    } else if (JSStringIsEqualToUTF8CString(character, "rightArrow")) {
        virtualKeyCode = VK_RIGHT;
        keyData += KF_EXTENDED << 16;
    } else if (JSStringIsEqualToUTF8CString(character, "upArrow")) {
        virtualKeyCode = VK_UP;
        keyData += KF_EXTENDED << 16;
    } else if (JSStringIsEqualToUTF8CString(character, "downArrow")) {
        virtualKeyCode = VK_DOWN;
        keyData += KF_EXTENDED << 16;
    } else if (JSStringIsEqualToUTF8CString(character, "pageUp"))
        virtualKeyCode = VK_PRIOR;
    else if (JSStringIsEqualToUTF8CString(character, "pageDown"))
        virtualKeyCode = VK_NEXT;
    else if (JSStringIsEqualToUTF8CString(character, "home"))
        virtualKeyCode = VK_HOME;
    else if (JSStringIsEqualToUTF8CString(character, "end"))
        virtualKeyCode = VK_END;
    else if (JSStringIsEqualToUTF8CString(character, "delete"))
        virtualKeyCode = VK_BACK;
    else {
        charCode = JSStringGetCharactersPtr(character)[0];
        virtualKeyCode = LOBYTE(VkKeyScan(charCode));
        if (WTF::isASCIIUpper(charCode))
            needsShiftKeyModifier = true;
    }
    JSStringRelease(character);

    BYTE keyState[256];
    if (argumentCount > 1 || needsShiftKeyModifier) {
        ::GetKeyboardState(keyState);

        BYTE newKeyState[256];
        memcpy(newKeyState, keyState, sizeof(keyState));

        if (needsShiftKeyModifier)
            newKeyState[VK_SHIFT] = 0x80;

        if (argumentCount > 1) {
            JSObjectRef modifiersArray = JSValueToObject(context, arguments[1], exception);
            if (modifiersArray) {
                int modifiersCount = JSValueToNumber(context, JSObjectGetProperty(context, modifiersArray, lengthProperty, 0), 0);
                for (int i = 0; i < modifiersCount; ++i) {
                    JSValueRef value = JSObjectGetPropertyAtIndex(context, modifiersArray, i, 0);
                    JSStringRef string = JSValueToStringCopy(context, value, 0);
                    if (JSStringIsEqualToUTF8CString(string, "ctrlKey"))
                        newKeyState[VK_CONTROL] = 0x80;
                    else if (JSStringIsEqualToUTF8CString(string, "shiftKey"))
                        newKeyState[VK_SHIFT] = 0x80;
                    else if (JSStringIsEqualToUTF8CString(string, "altKey"))
                        newKeyState[VK_MENU] = 0x80;

                    JSStringRelease(string);
                }
            }
        }

        ::SetKeyboardState(newKeyState);
    }

    MSG msg = makeMsg(webViewWindow, (::GetKeyState(VK_MENU) & 0x8000) ? WM_SYSKEYDOWN : WM_KEYDOWN, virtualKeyCode, keyData);
    if (virtualKeyCode != 255)
        dispatchMessage(&msg);
    else {
        // For characters that do not exist in the active keyboard layout,
        // ::Translate will not work, so we post an WM_CHAR event ourselves.
        ::PostMessage(webViewWindow, WM_CHAR, charCode, 0);
    }

    // Tests expect that all messages are processed by the time keyDown() returns.
    if (::PeekMessage(&msg, webViewWindow, WM_CHAR, WM_CHAR, PM_REMOVE) || ::PeekMessage(&msg, webViewWindow, WM_SYSCHAR, WM_SYSCHAR, PM_REMOVE))
        ::DispatchMessage(&msg);

    MSG msgUp = makeMsg(webViewWindow, (::GetKeyState(VK_MENU) & 0x8000) ? WM_SYSKEYUP : WM_KEYUP, virtualKeyCode, keyData);
    ::DispatchMessage(&msgUp);

    if (argumentCount > 1 || needsShiftKeyModifier)
        ::SetKeyboardState(keyState);

    return JSValueMakeUndefined(context);
}

// eventSender.dispatchMessage(message, wParam, lParam, time = currentEventTime(), x = lastMousePosition.x, y = lastMousePosition.y)
static JSValueRef dispatchMessageCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
{
    if (argumentCount < 3)
        return JSValueMakeUndefined(context);

    COMPtr<IWebFramePrivate> framePrivate;
    if (SUCCEEDED(frame->QueryInterface(&framePrivate)))
        framePrivate->layout();
    
    MSG msg = {};
    msg.hwnd = webViewWindow;
    msg.message = JSValueToNumber(context, arguments[0], exception);
    ASSERT(!*exception);
    msg.wParam = JSValueToNumber(context, arguments[1], exception);
    ASSERT(!*exception);
    msg.lParam = static_cast<ULONG_PTR>(JSValueToNumber(context, arguments[2], exception));
    ASSERT(!*exception);
    if (argumentCount >= 4) {
        msg.time = JSValueToNumber(context, arguments[3], exception);
        ASSERT(!*exception);
    }
    if (!msg.time)
        msg.time = currentEventTime();
    if (argumentCount >= 6) {
        msg.pt.x = JSValueToNumber(context, arguments[4], exception);
        ASSERT(!*exception);
        msg.pt.y = JSValueToNumber(context, arguments[5], exception);
        ASSERT(!*exception);
    } else
        msg.pt = lastMousePosition;

    ::DispatchMessage(&msg);

    return JSValueMakeUndefined(context);
}

static JSValueRef textZoomInCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
{
    COMPtr<IWebView> webView;
    if (FAILED(frame->webView(&webView)))
        return JSValueMakeUndefined(context);

    COMPtr<IWebIBActions> webIBActions;
    if (FAILED(webView->QueryInterface(IID_IWebIBActions, (void**)&webIBActions)))
        return JSValueMakeUndefined(context);

    webIBActions->makeTextLarger(0);
    return JSValueMakeUndefined(context);
}

static JSValueRef textZoomOutCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
{
    COMPtr<IWebView> webView;
    if (FAILED(frame->webView(&webView)))
        return JSValueMakeUndefined(context);

    COMPtr<IWebIBActions> webIBActions;
    if (FAILED(webView->QueryInterface(IID_IWebIBActions, (void**)&webIBActions)))
        return JSValueMakeUndefined(context);

    webIBActions->makeTextSmaller(0);
    return JSValueMakeUndefined(context);
}

static JSStaticFunction staticFunctions[] = {
    { "contextClick", contextClickCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
    { "mouseDown", mouseDownCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
    { "mouseUp", mouseUpCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
    { "mouseMoveTo", mouseMoveToCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
    { "leapForward", leapForwardCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
    { "keyDown", keyDownCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
    { "dispatchMessage", dispatchMessageCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
    { "textZoomIn", textZoomInCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
    { "textZoomOut", textZoomOutCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
    { 0, 0, 0 }
};

static JSStaticValue staticValues[] = {
    { "dragMode", getDragModeCallback, setDragModeCallback, kJSPropertyAttributeNone },
    { "WM_KEYDOWN", getConstantCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeNone },
    { "WM_KEYUP", getConstantCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeNone },
    { "WM_CHAR", getConstantCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeNone },
    { "WM_DEADCHAR", getConstantCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeNone },
    { "WM_SYSKEYDOWN", getConstantCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeNone },
    { "WM_SYSKEYUP", getConstantCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeNone },
    { "WM_SYSCHAR", getConstantCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeNone },
    { "WM_SYSDEADCHAR", getConstantCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeNone },
    { 0, 0, 0, 0 }
};

static JSClassRef getClass(JSContextRef context)
{
    static JSClassRef eventSenderClass = 0;

    if (!eventSenderClass) {
        JSClassDefinition classDefinition = {0};
        classDefinition.staticFunctions = staticFunctions;
        classDefinition.staticValues = staticValues;

        eventSenderClass = JSClassCreate(&classDefinition);
    }

    return eventSenderClass;
}

JSObjectRef makeEventSender(JSContextRef context)
{
    down = false;
    dragMode = true;
    replayingSavedEvents = false;
    timeOffset = 0;
    lastMousePosition.x = 0;
    lastMousePosition.y = 0;

    endOfQueue = 0;
    startOfQueue = 0;

    didDragEnter = false;
    draggingInfo = 0;

    return JSObjectMake(context, getClass(context), 0);
}
