/*
 * Copyright (C) 2011, 2015 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.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 INC. 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.
 */

#import "config.h"
#import "ScrollAnimatorIOS.h"

#if PLATFORM(IOS)

#import "Frame.h"
#import "RenderLayer.h"
#import "ScrollableArea.h"

#if ENABLE(TOUCH_EVENTS)
#import "PlatformTouchEventIOS.h"
#endif

namespace WebCore {

std::unique_ptr<ScrollAnimator> ScrollAnimator::create(ScrollableArea& scrollableArea)
{
    return std::make_unique<ScrollAnimatorIOS>(scrollableArea);
}

ScrollAnimatorIOS::ScrollAnimatorIOS(ScrollableArea& scrollableArea)
    : ScrollAnimator(scrollableArea)
#if ENABLE(TOUCH_EVENTS)
    , m_touchScrollAxisLatch(AxisLatchNotComputed)
    , m_inTouchSequence(false)
    , m_committedToScrollAxis(false)
    , m_startedScroll(false)
    , m_scrollableAreaForTouchSequence(0)
#endif
{
}

ScrollAnimatorIOS::~ScrollAnimatorIOS()
{
}

#if ENABLE(TOUCH_EVENTS)
bool ScrollAnimatorIOS::handleTouchEvent(const PlatformTouchEvent& touchEvent)
{
    if (touchEvent.type() == PlatformEvent::TouchStart && touchEvent.touchCount() == 1) {
        m_firstTouchPoint = touchEvent.touchLocationAtIndex(0);
        m_lastTouchPoint = m_firstTouchPoint;
        m_inTouchSequence = true;
        m_committedToScrollAxis = false;
        m_startedScroll = false;
        m_touchScrollAxisLatch = AxisLatchNotComputed;
        // Never claim to have handled the TouchStart, because that will kill default scrolling behavior.
        return false;
    }

    if (!m_inTouchSequence)
        return false;

    if (touchEvent.type() == PlatformEvent::TouchEnd || touchEvent.type() == PlatformEvent::TouchCancel) {
        m_inTouchSequence = false;
        m_scrollableAreaForTouchSequence = 0;
        if (m_startedScroll)
            scrollableArea().didEndScroll();
        return false;
    }

    // If a second touch appears, assume that the user is trying to zoom, and bail on the scrolling sequence.
    // FIXME: if that second touch is inside the scrollable area, should we keep scrolling?
    if (touchEvent.touchCount() != 1) {
        m_inTouchSequence = false;
        m_scrollableAreaForTouchSequence = 0;
        if (m_startedScroll)
            scrollableArea().didEndScroll();
        return false;
    }
    
    IntPoint currentPoint = touchEvent.touchLocationAtIndex(0);

    IntSize touchDelta = m_lastTouchPoint - currentPoint;
    m_lastTouchPoint = currentPoint;

    if (!m_scrollableAreaForTouchSequence)
        determineScrollableAreaForTouchSequence(touchDelta);

    if (!m_committedToScrollAxis) {
        bool horizontallyScrollable = m_scrollableArea.scrollSize(HorizontalScrollbar);
        bool verticallyScrollable = m_scrollableArea.scrollSize(VerticalScrollbar);

        if (!horizontallyScrollable && !verticallyScrollable)
            return false;

        IntSize deltaFromStart = m_firstTouchPoint - currentPoint;
    
        const int latchAxisMovementThreshold = 10;
        if (!horizontallyScrollable && verticallyScrollable) {
            m_touchScrollAxisLatch = AxisLatchVertical;
            if (abs(deltaFromStart.height()) >= latchAxisMovementThreshold)
                m_committedToScrollAxis = true;
        } else if (horizontallyScrollable && !verticallyScrollable) {
            m_touchScrollAxisLatch = AxisLatchHorizontal;
            if (abs(deltaFromStart.width()) >= latchAxisMovementThreshold)
                m_committedToScrollAxis = true;
        } else {
            m_committedToScrollAxis = true;

            if (m_touchScrollAxisLatch == AxisLatchNotComputed) {
                const float lockAngleDegrees = 20;
                if (deltaFromStart.width() && deltaFromStart.height()) {
                    float dragAngle = atanf(static_cast<float>(abs(deltaFromStart.height())) / abs(deltaFromStart.width()));
                    if (dragAngle <= deg2rad(lockAngleDegrees))
                        m_touchScrollAxisLatch = AxisLatchHorizontal;
                    else if (dragAngle >= deg2rad(90 - lockAngleDegrees))
                        m_touchScrollAxisLatch = AxisLatchVertical;
                }
            }
        }
        
        if (!m_committedToScrollAxis)
            return false;
    }

    bool handled = false;
    
    // Horizontal
    if (m_touchScrollAxisLatch != AxisLatchVertical) {
        int delta = touchDelta.width();
        handled |= m_scrollableAreaForTouchSequence->scroll(delta < 0 ? ScrollLeft : ScrollRight, ScrollByPixel, abs(delta));
    }
    
    // Vertical
    if (m_touchScrollAxisLatch != AxisLatchHorizontal) {
        int delta = touchDelta.height();
        handled |= m_scrollableAreaForTouchSequence->scroll(delta < 0 ? ScrollUp : ScrollDown, ScrollByPixel, abs(delta));
    }
    
    // Return false until we manage to scroll at all, and then keep returning true until the gesture ends.
    if (!m_startedScroll) {
        if (!handled)
            return false;
        m_startedScroll = true;
        scrollableArea().didStartScroll();
    } else if (handled)
        scrollableArea().didUpdateScroll();
    
    return true;
}

void ScrollAnimatorIOS::determineScrollableAreaForTouchSequence(const IntSize& scrollDelta)
{
    ASSERT(!m_scrollableAreaForTouchSequence);

    ScrollableArea* scrollableArea = &m_scrollableArea;
    while (true) {
        if (!scrollableArea->isPinnedInBothDirections(scrollDelta))
            break;

        ScrollableArea* enclosingArea = scrollableArea->enclosingScrollableArea();
        if (!enclosingArea)
            break;

        scrollableArea = enclosingArea;
    }

    ASSERT(scrollableArea);
    m_scrollableAreaForTouchSequence = scrollableArea;
}
#endif

} // namespace WebCore

#endif // PLATFORM(IOS)
