/*
 * Copyright (C) 2009 Google 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:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * 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.
 *     * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
 * OWNER OR 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 "WebInputEventConversion.h"

#include "EventNames.h"
#include "KeyboardCodes.h"
#include "KeyboardEvent.h"
#include "MouseEvent.h"
#include "PlatformKeyboardEvent.h"
#include "PlatformMouseEvent.h"
#include "PlatformWheelEvent.h"
#include "ScrollView.h"
#include "WebInputEvent.h"
#include "WheelEvent.h"
#include "Widget.h"

using namespace WebCore;

namespace WebKit {

// MakePlatformMouseEvent -----------------------------------------------------

PlatformMouseEventBuilder::PlatformMouseEventBuilder(Widget* widget, const WebMouseEvent& e)
{
    // FIXME: widget is always toplevel, unless it's a popup.  We may be able
    // to get rid of this once we abstract popups into a WebKit API.
    m_position = widget->convertFromContainingWindow(IntPoint(e.x, e.y));
    m_globalPosition = IntPoint(e.globalX, e.globalY);
    m_button = static_cast<MouseButton>(e.button);
    m_shiftKey = (e.modifiers & WebInputEvent::ShiftKey);
    m_ctrlKey = (e.modifiers & WebInputEvent::ControlKey);
    m_altKey = (e.modifiers & WebInputEvent::AltKey);
    m_metaKey = (e.modifiers & WebInputEvent::MetaKey);
    m_modifierFlags = e.modifiers;
    m_timestamp = e.timeStampSeconds;
    m_clickCount = e.clickCount;

    switch (e.type) {
    case WebInputEvent::MouseMove:
    case WebInputEvent::MouseLeave:  // synthesize a move event
        m_eventType = MouseEventMoved;
        break;

    case WebInputEvent::MouseDown:
        m_eventType = MouseEventPressed;
        break;

    case WebInputEvent::MouseUp:
        m_eventType = MouseEventReleased;
        break;

    default:
        ASSERT_NOT_REACHED();
    }
}

// PlatformWheelEventBuilder --------------------------------------------------

PlatformWheelEventBuilder::PlatformWheelEventBuilder(Widget* widget, const WebMouseWheelEvent& e)
{
    m_position = widget->convertFromContainingWindow(IntPoint(e.x, e.y));
    m_globalPosition = IntPoint(e.globalX, e.globalY);
    m_deltaX = e.deltaX;
    m_deltaY = e.deltaY;
    m_wheelTicksX = e.wheelTicksX;
    m_wheelTicksY = e.wheelTicksY;
    m_isAccepted = false;
    m_granularity = e.scrollByPage ?
        ScrollByPageWheelEvent : ScrollByPixelWheelEvent;
    m_shiftKey = (e.modifiers & WebInputEvent::ShiftKey);
    m_ctrlKey = (e.modifiers & WebInputEvent::ControlKey);
    m_altKey = (e.modifiers & WebInputEvent::AltKey);
    m_metaKey = (e.modifiers & WebInputEvent::MetaKey);
}

// MakePlatformKeyboardEvent --------------------------------------------------

static inline PlatformKeyboardEvent::Type toPlatformKeyboardEventType(WebInputEvent::Type type)
{
    switch (type) {
    case WebInputEvent::KeyUp:
        return PlatformKeyboardEvent::KeyUp;
    case WebInputEvent::KeyDown:
        return PlatformKeyboardEvent::KeyDown;
    case WebInputEvent::RawKeyDown:
        return PlatformKeyboardEvent::RawKeyDown;
    case WebInputEvent::Char:
        return PlatformKeyboardEvent::Char;
    default:
        ASSERT_NOT_REACHED();
    }
    return PlatformKeyboardEvent::KeyDown;
}

PlatformKeyboardEventBuilder::PlatformKeyboardEventBuilder(const WebKeyboardEvent& e)
{
    m_type = toPlatformKeyboardEventType(e.type);
    m_text = String(e.text);
    m_unmodifiedText = String(e.unmodifiedText);
    m_keyIdentifier = String(e.keyIdentifier);
    m_autoRepeat = (e.modifiers & WebInputEvent::IsAutoRepeat);
    m_windowsVirtualKeyCode = e.windowsKeyCode;
    m_nativeVirtualKeyCode = e.nativeKeyCode;
    m_isKeypad = (e.modifiers & WebInputEvent::IsKeyPad);
    m_shiftKey = (e.modifiers & WebInputEvent::ShiftKey);
    m_ctrlKey = (e.modifiers & WebInputEvent::ControlKey);
    m_altKey = (e.modifiers & WebInputEvent::AltKey);
    m_metaKey = (e.modifiers & WebInputEvent::MetaKey);
    m_isSystemKey = e.isSystemKey;
}

void PlatformKeyboardEventBuilder::setKeyType(Type type)
{
    // According to the behavior of Webkit in Windows platform,
    // we need to convert KeyDown to RawKeydown and Char events
    // See WebKit/WebKit/Win/WebView.cpp
    ASSERT(m_type == KeyDown);
    ASSERT(type == RawKeyDown || type == Char);
    m_type = type;

    if (type == RawKeyDown) {
        m_text = String();
        m_unmodifiedText = String();
    } else {
        m_keyIdentifier = String();
        m_windowsVirtualKeyCode = 0;
    }
}

// Please refer to bug http://b/issue?id=961192, which talks about Webkit
// keyboard event handling changes. It also mentions the list of keys
// which don't have associated character events.
bool PlatformKeyboardEventBuilder::isCharacterKey() const
{
    switch (windowsVirtualKeyCode()) {
    case VKEY_BACK:
    case VKEY_ESCAPE:
        return false;
    }
    return true;
}

#if ENABLE(TOUCH_EVENTS)
static inline TouchEventType toPlatformTouchEventType(const WebInputEvent::Type type)
{
    switch (type) {
    case WebInputEvent::TouchStart:
        return TouchStart;
    case WebInputEvent::TouchMove:
        return TouchMove;
    case WebInputEvent::TouchEnd:
        return TouchEnd;
    case WebInputEvent::TouchCancel:
        return TouchCancel;
    default:
        ASSERT_NOT_REACHED();
    }
    return TouchStart;
}

static inline PlatformTouchPoint::State toPlatformTouchPointState(const WebTouchPoint::State state)
{
    switch (state) {
    case WebTouchPoint::StateReleased:
        return PlatformTouchPoint::TouchReleased;
    case WebTouchPoint::StatePressed:
        return PlatformTouchPoint::TouchPressed;
    case WebTouchPoint::StateMoved:
        return PlatformTouchPoint::TouchMoved;
    case WebTouchPoint::StateStationary:
        return PlatformTouchPoint::TouchStationary;
    case WebTouchPoint::StateCancelled:
        return PlatformTouchPoint::TouchCancelled;
    case WebTouchPoint::StateUndefined:
        ASSERT_NOT_REACHED();
    }
    return PlatformTouchPoint::TouchReleased;
}

PlatformTouchPointBuilder::PlatformTouchPointBuilder(Widget* widget, const WebTouchPoint& point)
{
    m_id = point.id;
    m_state = toPlatformTouchPointState(point.state);
    m_pos = widget->convertFromContainingWindow(point.position);
    m_screenPos = point.screenPosition;
}

PlatformTouchEventBuilder::PlatformTouchEventBuilder(Widget* widget, const WebTouchEvent& event)
{
    m_type = toPlatformTouchEventType(event.type);
    m_ctrlKey = event.modifiers & WebInputEvent::ControlKey;
    m_altKey = event.modifiers & WebInputEvent::AltKey;
    m_shiftKey = event.modifiers & WebInputEvent::ShiftKey;
    m_metaKey = event.modifiers & WebInputEvent::MetaKey;
    m_timestamp = event.timeStampSeconds;

    for (int i = 0; i < event.touchPointsLength; ++i)
        m_touchPoints.append(PlatformTouchPointBuilder(widget, event.touchPoints[i]));
}
#endif

static int getWebInputModifiers(const UIEventWithKeyState& event)
{
    int modifiers = 0;
    if (event.ctrlKey())
        modifiers |= WebInputEvent::ControlKey;
    if (event.shiftKey())
        modifiers |= WebInputEvent::ShiftKey;
    if (event.altKey())
        modifiers |= WebInputEvent::AltKey;
    if (event.metaKey())
        modifiers |= WebInputEvent::MetaKey;
    return modifiers;
}

WebMouseEventBuilder::WebMouseEventBuilder(const Widget* widget, const MouseEvent& event)
{
    if (event.type() == eventNames().mousemoveEvent)
        type = WebInputEvent::MouseMove;
    else if (event.type() == eventNames().mouseoutEvent)
        type = WebInputEvent::MouseLeave;
    else if (event.type() == eventNames().mouseoverEvent)
        type = WebInputEvent::MouseEnter;
    else if (event.type() == eventNames().mousedownEvent)
        type = WebInputEvent::MouseDown;
    else if (event.type() == eventNames().mouseupEvent)
        type = WebInputEvent::MouseUp;
    else if (event.type() == eventNames().contextmenuEvent)
        type = WebInputEvent::ContextMenu;
    else
        return; // Skip all other mouse events.
    timeStampSeconds = event.timeStamp() * 1.0e-3;
    switch (event.button()) {
    case LeftButton:
        button = WebMouseEvent::ButtonLeft;
        break;
    case MiddleButton:
        button = WebMouseEvent::ButtonMiddle;
        break;
    case RightButton:
        button = WebMouseEvent::ButtonRight;
        break;
    }
    modifiers = getWebInputModifiers(event);
    if (event.buttonDown()) {
        switch (event.button()) {
        case LeftButton:
            modifiers |= WebInputEvent::LeftButtonDown;
            break;
        case MiddleButton:
            modifiers |= WebInputEvent::MiddleButtonDown;
            break;
        case RightButton:
            modifiers |= WebInputEvent::RightButtonDown;
            break;
        }
    }
    ScrollView* view = widget->parent();
    IntPoint p = view->contentsToWindow(
        IntPoint(event.absoluteLocation().x(), event.absoluteLocation().y()));
    globalX = event.screenX();
    globalY = event.screenY();
    windowX = p.x();
    windowY = p.y();
    x = event.absoluteLocation().x() - widget->pos().x();
    y = event.absoluteLocation().y() - widget->pos().y();
    clickCount = event.detail();
}

WebMouseWheelEventBuilder::WebMouseWheelEventBuilder(const Widget* widget, const WheelEvent& event)
{
    if (event.type() != eventNames().mousewheelEvent)
        return;
    type = WebInputEvent::MouseWheel;
    timeStampSeconds = event.timeStamp() * 1.0e-3;
    modifiers = getWebInputModifiers(event);
    ScrollView* view = widget->parent();
    IntPoint p = view->contentsToWindow(
        IntPoint(event.absoluteLocation().x(), event.absoluteLocation().y()));
    globalX = event.screenX();
    globalY = event.screenY();
    windowX = p.x();
    windowY = p.y();
    x = event.absoluteLocation().x() - widget->pos().x();
    y = event.absoluteLocation().y() - widget->pos().y();
    deltaX = static_cast<float>(event.rawDeltaX());
    deltaY = static_cast<float>(event.rawDeltaY());
    // The 120 is from WheelEvent::initWheelEvent().
    wheelTicksX = static_cast<float>(event.wheelDeltaX()) / 120;
    wheelTicksY = static_cast<float>(event.wheelDeltaY()) / 120;
    scrollByPage = event.granularity() == WheelEvent::Page;
}

WebKeyboardEventBuilder::WebKeyboardEventBuilder(const KeyboardEvent& event)
{
    if (event.type() == eventNames().keydownEvent)
        type = KeyDown;
    else if (event.type() == eventNames().keyupEvent)
        type = WebInputEvent::KeyUp;
    else if (event.type() == eventNames().keypressEvent)
        type = WebInputEvent::Char;
    else
        return; // Skip all other keyboard events.
    modifiers = getWebInputModifiers(event);
    timeStampSeconds = event.timeStamp() * 1.0e-3;
    windowsKeyCode = event.keyCode();

    // The platform keyevent does not exist if the event was created using
    // initKeyboardEvent.
    if (!event.keyEvent())
        return;
    nativeKeyCode = event.keyEvent()->nativeVirtualKeyCode();
    unsigned int numChars = std::min(event.keyEvent()->text().length(),
        static_cast<unsigned int>(WebKeyboardEvent::textLengthCap));
    for (unsigned int i = 0; i < numChars; i++) {
        text[i] = event.keyEvent()->text()[i];
        unmodifiedText[i] = event.keyEvent()->unmodifiedText()[i];
    }
}

} // namespace WebKit
