/*
 * Copyright (C) 2011 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:
 *
 * 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.
 *
 * 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 "WebCompositorInputHandlerImpl.h"

#include "PlatformGestureCurveFactory.h"
#include "PlatformGestureCurveTarget.h"
#include "TraceEvent.h"
#include "WebCompositorInputHandlerClient.h"
#include "WebInputEvent.h"
#include <public/WebInputHandlerClient.h>
#include <wtf/ThreadingPrimitives.h>

using namespace WebCore;

namespace WebKit {

// These statics may only be accessed from the compositor thread.
int WebCompositorInputHandlerImpl::s_nextAvailableIdentifier = 1;
HashSet<WebCompositorInputHandlerImpl*>* WebCompositorInputHandlerImpl::s_compositors = 0;

WebCompositorInputHandler* WebCompositorInputHandler::fromIdentifier(int identifier)
{
    return WebCompositorInputHandlerImpl::fromIdentifier(identifier);
}

WebCompositorInputHandler* WebCompositorInputHandlerImpl::fromIdentifier(int identifier)
{

    if (!s_compositors)
        return 0;

    for (HashSet<WebCompositorInputHandlerImpl*>::iterator it = s_compositors->begin(); it != s_compositors->end(); ++it) {
        if ((*it)->identifier() == identifier)
            return *it;
    }
    return 0;
}

WebCompositorInputHandlerImpl::WebCompositorInputHandlerImpl()
    : m_client(0)
    , m_identifier(s_nextAvailableIdentifier++)
    , m_inputHandlerClient(0)
#ifndef NDEBUG
    , m_expectScrollUpdateEnd(false)
    , m_expectPinchUpdateEnd(false)
#endif
    , m_gestureScrollStarted(false)
{
}

WebCompositorInputHandlerImpl::~WebCompositorInputHandlerImpl()
{
    if (m_client)
        m_client->willShutdown();

    ASSERT(s_compositors);
    s_compositors->remove(this);
    if (!s_compositors->size()) {
        delete s_compositors;
        s_compositors = 0;
    }
}

void WebCompositorInputHandlerImpl::setClient(WebCompositorInputHandlerClient* client)
{
    // It's valid to set a new client if we've never had one or to clear the client, but it's not valid to change from having one client to a different one.
    ASSERT(!m_client || !client);
    m_client = client;
}

void WebCompositorInputHandlerImpl::handleInputEvent(const WebInputEvent& event)
{
    ASSERT(m_client);

    WebCompositorInputHandlerImpl::EventDisposition disposition = handleInputEventInternal(event);
    switch (disposition) {
    case DidHandle:
        m_client->didHandleInputEvent();
        break;
    case DidNotHandle:
        m_client->didNotHandleInputEvent(true /* sendToWidget */);
        break;
    case DropEvent:
        m_client->didNotHandleInputEvent(false /* sendToWidget */);
        break;
    }
}

WebCompositorInputHandlerImpl::EventDisposition WebCompositorInputHandlerImpl::handleInputEventInternal(const WebInputEvent& event)
{
    if (event.type == WebInputEvent::MouseWheel) {
        const WebMouseWheelEvent& wheelEvent = *static_cast<const WebMouseWheelEvent*>(&event);
        WebInputHandlerClient::ScrollStatus scrollStatus = m_inputHandlerClient->scrollBegin(WebPoint(wheelEvent.x, wheelEvent.y), WebInputHandlerClient::ScrollInputTypeWheel);
        switch (scrollStatus) {
        case WebInputHandlerClient::ScrollStatusStarted: {
            TRACE_EVENT_INSTANT2("cc", "WebCompositorInputHandlerImpl::handleInput wheel scroll", "deltaX", -wheelEvent.deltaX, "deltaY", -wheelEvent.deltaY);
            m_inputHandlerClient->scrollBy(WebPoint(wheelEvent.x, wheelEvent.y), IntSize(-wheelEvent.deltaX, -wheelEvent.deltaY));
            m_inputHandlerClient->scrollEnd();
            return DidHandle;
        }
        case WebInputHandlerClient::ScrollStatusIgnored:
            // FIXME: This should be DropEvent, but in cases where we fail to properly sync scrollability it's safer to send the
            // event to the main thread. Change back to DropEvent once we have synchronization bugs sorted out.
            return DidNotHandle; 
        case WebInputHandlerClient::ScrollStatusOnMainThread:
            return DidNotHandle;
        }
    } else if (event.type == WebInputEvent::GestureScrollBegin) {
        ASSERT(!m_gestureScrollStarted);
        ASSERT(!m_expectScrollUpdateEnd);
#ifndef NDEBUG
        m_expectScrollUpdateEnd = true;
#endif
        const WebGestureEvent& gestureEvent = *static_cast<const WebGestureEvent*>(&event);
        WebInputHandlerClient::ScrollStatus scrollStatus = m_inputHandlerClient->scrollBegin(WebPoint(gestureEvent.x, gestureEvent.y), WebInputHandlerClient::ScrollInputTypeGesture);
        switch (scrollStatus) {
        case WebInputHandlerClient::ScrollStatusStarted:
            m_gestureScrollStarted = true;
            return DidHandle;
        case WebInputHandlerClient::ScrollStatusOnMainThread:
            return DidNotHandle;
        case WebInputHandlerClient::ScrollStatusIgnored:
            return DropEvent;
        }
    } else if (event.type == WebInputEvent::GestureScrollUpdate) {
        ASSERT(m_expectScrollUpdateEnd);

        if (!m_gestureScrollStarted)
            return DidNotHandle;

        const WebGestureEvent& gestureEvent = *static_cast<const WebGestureEvent*>(&event);
        m_inputHandlerClient->scrollBy(WebPoint(gestureEvent.x, gestureEvent.y),
            IntSize(-gestureEvent.data.scrollUpdate.deltaX, -gestureEvent.data.scrollUpdate.deltaY));
        return DidHandle;
    } else if (event.type == WebInputEvent::GestureScrollEnd) {
        ASSERT(m_expectScrollUpdateEnd);
#ifndef NDEBUG
        m_expectScrollUpdateEnd = false;
#endif
        if (!m_gestureScrollStarted)
            return DidNotHandle;

        m_inputHandlerClient->scrollEnd();
        m_gestureScrollStarted = false;
        return DidHandle;
    } else if (event.type == WebInputEvent::GesturePinchBegin) {
        ASSERT(!m_expectPinchUpdateEnd);
#ifndef NDEBUG
        m_expectPinchUpdateEnd = true;
#endif
        m_inputHandlerClient->pinchGestureBegin();
        return DidHandle;
    } else if (event.type == WebInputEvent::GesturePinchEnd) {
        ASSERT(m_expectPinchUpdateEnd);
#ifndef NDEBUG
        m_expectPinchUpdateEnd = false;
#endif
        m_inputHandlerClient->pinchGestureEnd();
        return DidHandle;
    } else if (event.type == WebInputEvent::GesturePinchUpdate) {
        ASSERT(m_expectPinchUpdateEnd);
        const WebGestureEvent& gestureEvent = *static_cast<const WebGestureEvent*>(&event);
        m_inputHandlerClient->pinchGestureUpdate(gestureEvent.data.pinchUpdate.scale, WebPoint(gestureEvent.x, gestureEvent.y));
        return DidHandle;
    } else if (event.type == WebInputEvent::GestureFlingStart) {
        const WebGestureEvent& gestureEvent = *static_cast<const WebGestureEvent*>(&event);
        return handleGestureFling(gestureEvent);
    } else if (event.type == WebInputEvent::GestureFlingCancel) {
        if (cancelCurrentFling())
            return DidHandle;
    } else if (WebInputEvent::isKeyboardEventType(event.type)) {
         cancelCurrentFling();
    }

    return DidNotHandle;
}

WebCompositorInputHandlerImpl::EventDisposition WebCompositorInputHandlerImpl::handleGestureFling(const WebGestureEvent& gestureEvent)
{
    WebInputHandlerClient::ScrollStatus scrollStatus = m_inputHandlerClient->scrollBegin(WebPoint(gestureEvent.x, gestureEvent.y), WebInputHandlerClient::ScrollInputTypeGesture);
    switch (scrollStatus) {
    case WebInputHandlerClient::ScrollStatusStarted: {
        m_inputHandlerClient->scrollEnd();
        m_wheelFlingCurve = PlatformGestureCurveFactory::get()->createCurve(gestureEvent.data.flingStart.sourceDevice, FloatPoint(gestureEvent.data.flingStart.velocityX, gestureEvent.data.flingStart.velocityY));
        TRACE_EVENT_ASYNC_BEGIN1("cc", "WebCompositorInputHandlerImpl::handleGestureFling::started", this, "curve", m_wheelFlingCurve->debugName());
        m_wheelFlingParameters.delta = WebFloatPoint(gestureEvent.data.flingStart.velocityX, gestureEvent.data.flingStart.velocityY);
        m_wheelFlingParameters.point = WebPoint(gestureEvent.x, gestureEvent.y);
        m_wheelFlingParameters.globalPoint = WebPoint(gestureEvent.globalX, gestureEvent.globalY);
        m_wheelFlingParameters.modifiers = gestureEvent.modifiers;
        m_wheelFlingParameters.sourceDevice = gestureEvent.data.flingStart.sourceDevice;
        m_inputHandlerClient->scheduleAnimation();
        return DidHandle;
    }
    case WebInputHandlerClient::ScrollStatusOnMainThread: {
        TRACE_EVENT_INSTANT0("cc", "WebCompositorInputHandlerImpl::handleGestureFling::scrollOnMainThread");
        return DidNotHandle;
    }
    case WebInputHandlerClient::ScrollStatusIgnored: {
        TRACE_EVENT_INSTANT0("cc", "WebCompositorInputHandlerImpl::handleGestureFling::ignored");
        // We still pass the curve to the main thread if there's nothing scrollable, in case something
        // registers a handler before the curve is over.
        return DidNotHandle;
    }
    }
    return DidNotHandle;
}

void WebCompositorInputHandlerImpl::bindToClient(WebInputHandlerClient* client)
{
    ASSERT(!m_inputHandlerClient);

    TRACE_EVENT_INSTANT0("cc", "WebCompositorInputHandlerImpl::bindToClient");
    if (!s_compositors)
        s_compositors = new HashSet<WebCompositorInputHandlerImpl*>;
    s_compositors->add(this);

    m_inputHandlerClient = client;
}

void WebCompositorInputHandlerImpl::animate(double monotonicTime)
{
    if (!m_wheelFlingCurve)
        return;

    if (!m_wheelFlingParameters.startTime) {
        m_wheelFlingParameters.startTime = monotonicTime;
        m_inputHandlerClient->scheduleAnimation();
        return;
    }

    if (m_wheelFlingCurve->apply(monotonicTime - m_wheelFlingParameters.startTime, this))
        m_inputHandlerClient->scheduleAnimation();
    else {
        TRACE_EVENT_INSTANT0("cc", "WebCompositorInputHandlerImpl::animate::flingOver");
        cancelCurrentFling();
    }
}

bool WebCompositorInputHandlerImpl::cancelCurrentFling()
{
    bool hadFlingAnimation = m_wheelFlingCurve;
    if (hadFlingAnimation)
        TRACE_EVENT_ASYNC_END0("cc", "WebCompositorInputHandlerImpl::handleGestureFling::started", this);

    TRACE_EVENT_INSTANT1("cc", "WebCompositorInputHandlerImpl::cancelCurrentFling", "hadFlingAnimation", hadFlingAnimation);
    m_wheelFlingCurve.clear();
    m_wheelFlingParameters = WebActiveWheelFlingParameters();
    return hadFlingAnimation;
}

void WebCompositorInputHandlerImpl::scrollBy(const IntPoint& increment)
{
    if (increment == IntPoint::zero())
        return;

    TRACE_EVENT2("cc", "WebCompositorInputHandlerImpl::scrollBy", "x", increment.x(), "y", increment.y());
    WebMouseWheelEvent syntheticWheel;
    syntheticWheel.type = WebInputEvent::MouseWheel;
    syntheticWheel.deltaX = increment.x();
    syntheticWheel.deltaY = increment.y();
    syntheticWheel.hasPreciseScrollingDeltas = true;
    syntheticWheel.x = m_wheelFlingParameters.point.x;
    syntheticWheel.y = m_wheelFlingParameters.point.y;
    syntheticWheel.globalX = m_wheelFlingParameters.globalPoint.x;
    syntheticWheel.globalY = m_wheelFlingParameters.globalPoint.y;
    syntheticWheel.modifiers = m_wheelFlingParameters.modifiers;

    WebCompositorInputHandlerImpl::EventDisposition disposition = handleInputEventInternal(syntheticWheel);
    switch (disposition) {
    case DidHandle:
        m_wheelFlingParameters.cumulativeScroll.width += increment.x();
        m_wheelFlingParameters.cumulativeScroll.height += increment.y();
    case DropEvent:
        break;
    case DidNotHandle:
        TRACE_EVENT_INSTANT0("cc", "WebCompositorInputHandlerImpl::scrollBy::AbortFling");
        // If we got a DidNotHandle, that means we need to deliver wheels on the main thread.
        // In this case we need to schedule a commit and transfer the fling curve over to the main
        // thread and run the rest of the wheels from there.
        // This can happen when flinging a page that contains a scrollable subarea that we can't
        // scroll on the thread if the fling starts outside the subarea but then is flung "under" the
        // pointer.
        m_client->transferActiveWheelFlingAnimation(m_wheelFlingParameters);
        cancelCurrentFling();
        break;
    }
}

}
