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

#import "Logging.h"
#import "PlatformWheelEvent.h"
#import "ScrollAnimationRubberBand.h"
#import "ScrollExtents.h"
#import "ScrollableArea.h"
#import "WheelEventDeltaFilter.h"
#import <pal/spi/mac/NSScrollViewSPI.h>
#import <sys/sysctl.h>
#import <sys/time.h>
#import <wtf/text/TextStream.h>

#if PLATFORM(MAC)

namespace WebCore {

static const Seconds scrollVelocityZeroingTimeout = 100_ms;
static const float rubberbandDirectionLockStretchRatio = 1;
static const float rubberbandMinimumRequiredDeltaBeforeStretch = 10;

static float elasticDeltaForReboundDelta(float delta)
{
    return _NSElasticDeltaForReboundDelta(delta);
}

static float reboundDeltaForElasticDelta(float delta)
{
    return _NSReboundDeltaForElasticDelta(delta);
}

static float scrollWheelMultiplier()
{
    static float multiplier = -1;
    if (multiplier < 0) {
        multiplier = [[NSUserDefaults standardUserDefaults] floatForKey:@"NSScrollWheelMultiplier"];
        if (multiplier <= 0)
            multiplier = 1;
    }
    return multiplier;
}

ScrollingEffectsController::~ScrollingEffectsController()
{
    ASSERT(m_timersWereStopped);
}

void ScrollingEffectsController::stopAllTimers()
{
    if (m_statelessSnapTransitionTimer)
        m_statelessSnapTransitionTimer->stop();

#if ASSERT_ENABLED
    m_timersWereStopped = true;
#endif
}

static ScrollEventAxis dominantAxisFavoringVertical(FloatSize delta)
{
    if (fabsf(delta.height()) >= fabsf(delta.width()))
        return ScrollEventAxis::Vertical;

    return ScrollEventAxis::Horizontal;
}

static FloatSize deltaAlignedToAxis(FloatSize delta, ScrollEventAxis axis)
{
    switch (axis) {
    case ScrollEventAxis::Horizontal: return FloatSize { delta.width(), 0 };
    case ScrollEventAxis::Vertical: return FloatSize { 0, delta.height() };
    }

    return { };
}

static FloatSize deltaAlignedToDominantAxis(FloatSize delta)
{
    auto dominantAxis = dominantAxisFavoringVertical(delta);
    return deltaAlignedToAxis(delta, dominantAxis);
}

static std::optional<BoxSide> affectedSideOnDominantAxis(FloatSize delta)
{
    auto dominantAxis = dominantAxisFavoringVertical(delta);
    return ScrollableArea::targetSideForScrollDelta(delta, dominantAxis);
}

#if !LOG_DISABLED
static const char* phaseToString(PlatformWheelEventPhase phase)
{
    switch (phase) {
    case PlatformWheelEventPhase::None: return "none";
    case PlatformWheelEventPhase::Began: return "began";
    case PlatformWheelEventPhase::Stationary: return "stationary";
    case PlatformWheelEventPhase::Changed: return "changed";
    case PlatformWheelEventPhase::Ended: return "ended";
    case PlatformWheelEventPhase::Cancelled: return "cancelled";
    case PlatformWheelEventPhase::MayBegin: return "mayBegin";
    }
    return "";
}
#endif

static FloatSize adjustedVelocity(FloatSize velocity)
{
    auto applyCurve = ^(float originalValue) {
        if (!originalValue)
            return originalValue;

        float value = fabs(originalValue);
        float powerLow = 6.7 * pow(value, -.166);
        float powerHigh = 36.3 * pow(value, -.392);
        const float transitionVelocity = 2000;

        auto interpolate = ^(float v0, float v1, float t) {
            return (1 - t) * v0 + t * v1;
        };
        
        float multiplier = interpolate(powerLow, powerHigh, std::min(value, transitionVelocity) / transitionVelocity);
        return copysign(value * multiplier, originalValue);
    };

    return { applyCurve(velocity.width()), applyCurve(velocity.height()) };
}

bool ScrollingEffectsController::handleWheelEvent(const PlatformWheelEvent& wheelEvent)
{
    if (processWheelEventForScrollSnap(wheelEvent))
        return true;

    if (wheelEvent.phase() == PlatformWheelEventPhase::MayBegin || wheelEvent.phase() == PlatformWheelEventPhase::Cancelled) {
        if (momentumScrollingAnimatorEnabled()) {
            LOG(ScrollAnimations, "Event (%s, %s): stopping animated scroll", phaseToString(wheelEvent.phase()), phaseToString(wheelEvent.momentumPhase()));
            stopAnimatedScroll();
        }
        return true;
    }

    if (wheelEvent.phase() == PlatformWheelEventPhase::Began) {
        if (momentumScrollingAnimatorEnabled()) {
            LOG(ScrollAnimations, "Event (%s, %s): stopping animated scroll", phaseToString(wheelEvent.phase()), phaseToString(wheelEvent.momentumPhase()));
            stopAnimatedScroll();
        }

        // FIXME: Trying to decide if a gesture is horizontal or vertical at the "began" phase is very error-prone.
        auto horizontalSide = ScrollableArea::targetSideForScrollDelta(-wheelEvent.delta(), ScrollEventAxis::Horizontal);
        if (horizontalSide && m_client.isPinnedOnSide(*horizontalSide) && !shouldRubberBandOnSide(*horizontalSide))
            return false;

        auto verticalSide = ScrollableArea::targetSideForScrollDelta(-wheelEvent.delta(), ScrollEventAxis::Vertical);
        if (verticalSide && m_client.isPinnedOnSide(*verticalSide) && !shouldRubberBandOnSide(*verticalSide))
            return false;

        m_momentumScrollInProgress = false;
        m_ignoreMomentumScrolls = false;
        m_lastMomentumScrollTimestamp = { };
        m_momentumVelocity = { };

        IntSize stretchAmount = m_client.stretchAmount();
        m_stretchScrollForce.setWidth(reboundDeltaForElasticDelta(stretchAmount.width()));
        m_stretchScrollForce.setHeight(reboundDeltaForElasticDelta(stretchAmount.height()));
        m_unappliedOverscrollDelta = { };

        stopRubberBandAnimation();
        updateRubberBandingState();
        return true;
    }

    if (wheelEvent.phase() == PlatformWheelEventPhase::Ended) {
        // FIXME: This triggers the rubberband timer even when we don't start rubberbanding.
        startRubberBandAnimationIfNecessary();
        updateRubberBandingState();
        return true;
    }

#if !LOG_DISABLED
    if (wheelEvent.momentumPhase() == PlatformWheelEventPhase::Began)
        m_momentumBeganEventTime = wheelEvent.timestamp();
#endif

    if (wheelEvent.momentumPhase() == PlatformWheelEventPhase::Ended && momentumScrollingAnimatorEnabled()) {
#if !LOG_DISABLED
        auto timeSinceStart = wheelEvent.timestamp() - m_momentumBeganEventTime;
        auto distance = m_eventDrivenScrollOffset - m_eventDrivenScrollMomentumStartOffset;
#endif
        // FIXME: We can't distinguish between the natural end of a momentum sequence, and a two-finger tap on the trackpad (rdar://85414238),
        // so we always have to end the animation here.
        LOG(ScrollAnimations, "Event (%s, %s): stopping event scroll duration %.2fms distance %.2f %.2f",
            phaseToString(wheelEvent.phase()), phaseToString(wheelEvent.momentumPhase()), timeSinceStart.milliseconds(),
            fabs(distance.width()), fabs(distance.height()));
        stopAnimatedNonRubberbandingScroll();
    }

    bool isMomentumScrollEvent = (wheelEvent.momentumPhase() != PlatformWheelEventPhase::None);
    if (m_ignoreMomentumScrolls && (isMomentumScrollEvent || m_isAnimatingRubberBand)) {
        if (wheelEvent.momentumPhase() == PlatformWheelEventPhase::Ended) {
            m_ignoreMomentumScrolls = false;
            return true;
        }

        if (isMomentumScrollEvent && m_ignoreMomentumScrolls)
            return true;

        return false;
    }

    IntSize stretchAmount = m_client.stretchAmount();
    bool isVerticallyStretched = stretchAmount.height();
    bool isHorizontallyStretched = stretchAmount.width();

    // Much of this code, including this use of unaccelerated deltas when stretched, is based on AppKit behavior.
    auto eventDelta = (isVerticallyStretched || isHorizontallyStretched) ? -wheelEvent.unacceleratedScrollingDelta() : -wheelEvent.delta();

    // Reset unapplied overscroll because we may decide to remove delta at various points and put it into this value.
    auto delta = std::exchange(m_unappliedOverscrollDelta, { });
    delta += eventDelta;
    // FIXME: This replicates what WheelEventDeltaFilter does. We should apply that to events in all phases, and remove axis locking here (webkit.org/b/231207).
    delta = deltaAlignedToDominantAxis(delta);

    auto momentumPhase = wheelEvent.momentumPhase();
    if (!m_momentumScrollInProgress && (momentumPhase == PlatformWheelEventPhase::Began || momentumPhase == PlatformWheelEventPhase::Changed)) {
        m_momentumScrollInProgress = true;
        if (momentumScrollingAnimatorEnabled()) {
            startMomentumScrollWithInitialVelocity(m_client.scrollOffset(), -adjustedVelocity(wheelEvent.scrollingVelocity()), -wheelEvent.delta(), [](const FloatPoint& targetOffset) { return targetOffset; });
#if !LOG_DISABLED
            m_eventDrivenScrollOffset = m_client.scrollOffset();
            m_eventDrivenScrollMomentumStartOffset = m_eventDrivenScrollOffset;
#endif
        }
    }

    if (momentumPhase == PlatformWheelEventPhase::Changed && momentumScrollingAnimatorEnabled()) {
#if !LOG_DISABLED
        m_eventDrivenScrollOffset -= wheelEvent.delta();
#endif
        LOG(ScrollAnimations, "Event (%s, %s): ignoring - would have scrolled to %.2f,%.2f", phaseToString(wheelEvent.phase()), phaseToString(wheelEvent.momentumPhase()),
            m_eventDrivenScrollOffset.x(), m_eventDrivenScrollOffset.y());
        return true;
    }

    bool shouldStretch = false;
    auto timeDelta = wheelEvent.timestamp() - m_lastMomentumScrollTimestamp;
    if (m_inScrollGesture || m_momentumScrollInProgress) {
        if (m_lastMomentumScrollTimestamp && timeDelta > 0_s && timeDelta < scrollVelocityZeroingTimeout) {
            m_momentumVelocity = eventDelta / timeDelta.seconds();
            m_lastMomentumScrollTimestamp = wheelEvent.timestamp();
        } else {
            m_lastMomentumScrollTimestamp = wheelEvent.timestamp();
            m_momentumVelocity = { };
        }

        shouldStretch = modifyScrollDeltaForStretching(wheelEvent, delta, isHorizontallyStretched, isVerticallyStretched);
    }

    bool handled = true;

    if (!delta.isZero()) {
        if (shouldStretch || isVerticallyStretched || isHorizontallyStretched) {
            if (delta.width() && !m_client.allowsHorizontalStretching(wheelEvent))
                handled = false;

            if (delta.height() && !m_client.allowsVerticalStretching(wheelEvent))
                handled = false;

            bool canStartAnimation = applyScrollDeltaWithStretching(wheelEvent, delta, isHorizontallyStretched, isVerticallyStretched);
            if (m_momentumScrollInProgress) {
                if (canStartAnimation && m_lastMomentumScrollTimestamp) {
                    m_ignoreMomentumScrolls = true;
                    m_momentumScrollInProgress = false;
                    startRubberBandAnimationIfNecessary();
                }
            }
        } else {
            delta.scale(scrollWheelMultiplier());
            m_client.immediateScrollBy(delta);
        }
    }

    if (m_momentumScrollInProgress && momentumPhase == PlatformWheelEventPhase::Ended) {
        m_momentumScrollInProgress = false;
        m_ignoreMomentumScrolls = false;
        m_lastMomentumScrollTimestamp = { };
    }

    updateRubberBandingState();

    return handled;
}

bool ScrollingEffectsController::modifyScrollDeltaForStretching(const PlatformWheelEvent& wheelEvent, FloatSize& delta, bool isHorizontallyStretched, bool isVerticallyStretched)
{
    auto affectedSide = affectedSideOnDominantAxis(delta);
    if (isVerticallyStretched) {
        if (!isHorizontallyStretched && affectedSide && m_client.isPinnedOnSide(*affectedSide)) {
            // Stretching only in the vertical.
            if (delta.height() && (fabsf(delta.width() / delta.height()) < rubberbandDirectionLockStretchRatio))
                delta.setWidth(0);
            else if (fabsf(delta.width()) < rubberbandMinimumRequiredDeltaBeforeStretch) {
                m_unappliedOverscrollDelta.expand(delta.width(), 0);
                delta.setWidth(0);
            } else
                m_unappliedOverscrollDelta.expand(delta.width(), 0);
        }

        return false;
    }

    if (isHorizontallyStretched) {
        // Stretching only in the horizontal.
        if (affectedSide && m_client.isPinnedOnSide(*affectedSide)) {
            if (delta.width() && (fabsf(delta.height() / delta.width()) < rubberbandDirectionLockStretchRatio))
                delta.setHeight(0);
            else if (fabsf(delta.height()) < rubberbandMinimumRequiredDeltaBeforeStretch) {
                m_unappliedOverscrollDelta.expand(0, delta.height());
                delta.setHeight(0);
            } else
                m_unappliedOverscrollDelta.expand(0, delta.height());
        }

        return false;
    }

    // Not stretching at all yet.
    if (affectedSide && m_client.isPinnedOnSide(*affectedSide)) {
        if (fabsf(delta.height()) >= fabsf(delta.width())) {
            if (fabsf(delta.width()) < rubberbandMinimumRequiredDeltaBeforeStretch) {
                m_unappliedOverscrollDelta.expand(delta.width(), 0);
                delta.setWidth(0);
            } else
                m_unappliedOverscrollDelta.expand(delta.width(), 0);
        }

        if (!m_client.allowsHorizontalStretching(wheelEvent))
            delta.setWidth(0);

        if (!m_client.allowsVerticalStretching(wheelEvent))
            delta.setHeight(0);

        return !delta.isZero();
    }
    
    return false;
}

bool ScrollingEffectsController::applyScrollDeltaWithStretching(const PlatformWheelEvent& wheelEvent, FloatSize delta, bool isHorizontallyStretched, bool isVerticallyStretched)
{
    auto eventDelta = (isVerticallyStretched || isHorizontallyStretched) ? -wheelEvent.unacceleratedScrollingDelta() : -wheelEvent.delta();
    auto affectedSide = affectedSideOnDominantAxis(delta);

    FloatSize deltaToScroll;

    if (delta.width()) {
        if (!m_client.allowsHorizontalStretching(wheelEvent)) {
            delta.setWidth(0);
            eventDelta.setWidth(0);
        } else if (!isHorizontallyStretched && !m_client.isPinnedOnSide(*affectedSide)) {
            delta.scale(scrollWheelMultiplier(), 1);
            deltaToScroll += FloatSize { delta.width(), 0 };
            delta.setWidth(0);
        }
    }

    if (delta.height()) {
        if (!m_client.allowsVerticalStretching(wheelEvent)) {
            delta.setHeight(0);
            eventDelta.setHeight(0);
        } else if (!isVerticallyStretched && !m_client.isPinnedOnSide(*affectedSide)) {
            delta.scale(1, scrollWheelMultiplier());
            deltaToScroll += FloatSize { 0, delta.height() };
            delta.setHeight(0);
        }
    }

    if (!deltaToScroll.isZero())
        m_client.immediateScrollBy(deltaToScroll, ScrollClamping::Unclamped);

    bool canStartAnimation = false;
    if (m_momentumScrollInProgress) {
        // Compute canStartAnimation, which looks at isPinnedOnSide(), before applying the stretch delta.
        auto sideAffectedByEventDelta = affectedSideOnDominantAxis(eventDelta);
        canStartAnimation = !sideAffectedByEventDelta || m_client.isPinnedOnSide(*sideAffectedByEventDelta);
    }

    m_stretchScrollForce += delta;
    auto dampedDelta = FloatSize {
        ceilf(elasticDeltaForReboundDelta(m_stretchScrollForce.width())),
        ceilf(elasticDeltaForReboundDelta(m_stretchScrollForce.height()))
    };

    LOG_WITH_STREAM(ScrollAnimations, stream << "ScrollingEffectsController::applyScrollDeltaWithStretching() - stretchScrollForce " << m_stretchScrollForce << " move delta " << delta << " dampedDelta " << dampedDelta);

    auto stretchAmount = m_client.stretchAmount();
    m_client.immediateScrollBy(dampedDelta - stretchAmount, ScrollClamping::Unclamped);

    return canStartAnimation;
}

FloatSize ScrollingEffectsController::wheelDeltaBiasingTowardsVertical(const PlatformWheelEvent& wheelEvent)
{
    return deltaAlignedToDominantAxis(wheelEvent.delta());
}

void ScrollingEffectsController::updateRubberBandAnimatingState()
{
    if (!m_isAnimatingRubberBand)
        return;

    if (isScrollSnapInProgress())
        return;
    
    if (m_momentumScrollInProgress && !m_ignoreMomentumScrolls) {
        LOG_WITH_STREAM(ScrollAnimations, stream << "ScrollingEffectsController::updateRubberBandAnimatingState() - not animating, momentumScrollInProgress " << m_momentumScrollInProgress << " ignoreMomentumScrolls " << m_ignoreMomentumScrolls);
        if (!isRubberBandInProgressInternal())
            stopRubberBandAnimation();
    }

    updateRubberBandingState();
}

void ScrollingEffectsController::scrollPositionChanged()
{
    updateRubberBandingState();
}

bool ScrollingEffectsController::isUserScrollInProgress() const
{
    return m_inScrollGesture;
}

bool ScrollingEffectsController::isRubberBandInProgress() const
{
    return m_isRubberBanding;
}

bool ScrollingEffectsController::isScrollSnapInProgress() const
{
    if (!usesScrollSnap())
        return false;

    if (m_inScrollGesture || m_momentumScrollInProgress || m_isAnimatingScrollSnap)
        return true;

    return false;
}

void ScrollingEffectsController::stopRubberBanding()
{
    stopRubberBandAnimation();
    updateRubberBandingState();
}

bool ScrollingEffectsController::startRubberBandAnimation(const FloatPoint& targetOffset, const FloatSize& initialVelocity, const FloatSize& initialOverscroll)
{
    if (is<ScrollAnimationMomentum>(m_currentAnimation) && m_currentAnimation->isActive()) {
        LOG_WITH_STREAM(ScrollAnimations, stream << "ScrollingEffectsController::startRubberBandAnimation() - momentum animation is present");
        return false;
    }

    if (m_currentAnimation)
        m_currentAnimation->stop();

    m_currentAnimation = makeUnique<ScrollAnimationRubberBand>(*this);
    bool started = downcast<ScrollAnimationRubberBand>(*m_currentAnimation).startRubberBandAnimation(targetOffset, initialVelocity, initialOverscroll);
    LOG_WITH_STREAM(ScrollAnimations, stream << "ScrollingEffectsController::startRubberBandAnimation() - animation " << *m_currentAnimation << " started " << started);
    return started;
}

void ScrollingEffectsController::stopRubberBandAnimation()
{
    if (m_isAnimatingRubberBand)
        stopAnimatedScroll();

    m_stretchScrollForce = { };
}

void ScrollingEffectsController::willStartRubberBandAnimation()
{
    m_isAnimatingRubberBand = true;
    m_client.willStartRubberBandAnimation();
    m_client.deferWheelEventTestCompletionForReason(reinterpret_cast<WheelEventTestMonitor::ScrollableAreaIdentifier>(this), WheelEventTestMonitor::RubberbandInProgress);
}

void ScrollingEffectsController::didStopRubberBandAnimation()
{
    m_isAnimatingRubberBand = false;
    m_client.didStopRubberBandAnimation();
    m_client.removeWheelEventTestCompletionDeferralForReason(reinterpret_cast<WheelEventTestMonitor::ScrollableAreaIdentifier>(this), WheelEventTestMonitor::RubberbandInProgress);
}

void ScrollingEffectsController::startRubberBandAnimationIfNecessary()
{
    auto timeDelta = WallTime::now() - m_lastMomentumScrollTimestamp;
    if (m_lastMomentumScrollTimestamp && timeDelta >= scrollVelocityZeroingTimeout)
        m_momentumVelocity = { };

    if (m_isAnimatingRubberBand)
        return;

    auto extents = m_client.scrollExtents();
    auto targetOffset = m_client.scrollOffset();
    auto contrainedOffset = targetOffset.constrainedBetween(extents.minimumScrollOffset(), extents.maximumScrollOffset());
    bool willOverscroll = targetOffset != contrainedOffset;

    auto stretchAmount = m_client.stretchAmount();
    if (stretchAmount.isZero() && !willOverscroll)
        return;

    auto initialVelocity = m_momentumVelocity;

    // Just like normal scrolling, prefer vertical rubberbanding
    if (fabsf(initialVelocity.height()) >= fabsf(initialVelocity.width()))
        initialVelocity.setWidth(0);

    // Don't rubber-band horizontally if it's not possible to scroll horizontally
    if (!m_client.allowsHorizontalScrolling())
        initialVelocity.setWidth(0);

    // Don't rubber-band vertically if it's not possible to scroll vertically
    if (!m_client.allowsVerticalScrolling())
        initialVelocity.setHeight(0);

    LOG_WITH_STREAM(ScrollAnimations, stream << "ScrollingEffectsController::startRubberBandAnimationIfNecessary() - rubberBandAnimationRunning " << m_isAnimatingRubberBand << " stretchAmount " << stretchAmount << " contrainedOffset " << contrainedOffset << " initialVelocity " << initialVelocity);
    startRubberBandAnimation(contrainedOffset, initialVelocity, stretchAmount);
}

bool ScrollingEffectsController::shouldRubberBandOnSide(BoxSide side) const
{
    return m_client.shouldRubberBandOnSide(side);
}

bool ScrollingEffectsController::isRubberBandInProgressInternal() const
{
    if (!m_inScrollGesture && !m_momentumScrollInProgress && !m_isAnimatingRubberBand)
        return false;

    return !m_client.stretchAmount().isZero();
}

void ScrollingEffectsController::updateRubberBandingState()
{
    bool isRubberBanding = isRubberBandInProgressInternal();
    if (isRubberBanding == m_isRubberBanding)
        return;

    LOG_WITH_STREAM(ScrollAnimations, stream << "ScrollingEffectsController " << this << " updateRubberBandingState - isRubberBanding " << isRubberBanding);

    m_isRubberBanding = isRubberBanding;
    if (m_isRubberBanding)
        updateRubberBandingEdges(m_client.stretchAmount());
    else
        m_rubberBandingEdges = { };

    m_client.rubberBandingStateChanged(m_isRubberBanding);
}

void ScrollingEffectsController::updateRubberBandingEdges(IntSize clientStretch)
{
    m_rubberBandingEdges.setLeft(clientStretch.width() < 0);
    m_rubberBandingEdges.setRight(clientStretch.width() > 0);

    m_rubberBandingEdges.setTop(clientStretch.height() < 0);
    m_rubberBandingEdges.setBottom(clientStretch.height() > 0);
}

enum class WheelEventStatus {
    UserScrollBegin,
    UserScrolling,
    UserScrollEnd,
    MomentumScrollBegin,
    MomentumScrolling,
    MomentumScrollEnd,
    StatelessScrollEvent,
    Unknown
};

static inline WheelEventStatus toWheelEventStatus(PlatformWheelEventPhase phase, PlatformWheelEventPhase momentumPhase)
{
    if (phase == PlatformWheelEventPhase::None) {
        switch (momentumPhase) {
        case PlatformWheelEventPhase::Began:
            return WheelEventStatus::MomentumScrollBegin;
                
        case PlatformWheelEventPhase::Changed:
            return WheelEventStatus::MomentumScrolling;
                
        case PlatformWheelEventPhase::Ended:
            return WheelEventStatus::MomentumScrollEnd;

        case PlatformWheelEventPhase::None:
            return WheelEventStatus::StatelessScrollEvent;

        default:
            return WheelEventStatus::Unknown;
        }
    }
    if (momentumPhase == PlatformWheelEventPhase::None) {
        switch (phase) {
        case PlatformWheelEventPhase::Began:
        case PlatformWheelEventPhase::MayBegin:
            return WheelEventStatus::UserScrollBegin;
                
        case PlatformWheelEventPhase::Changed:
            return WheelEventStatus::UserScrolling;
                
        case PlatformWheelEventPhase::Ended:
        case PlatformWheelEventPhase::Cancelled:
            return WheelEventStatus::UserScrollEnd;
                
        default:
            return WheelEventStatus::Unknown;
        }
    }
    return WheelEventStatus::Unknown;
}

#if !LOG_DISABLED
static TextStream& operator<<(TextStream& ts, WheelEventStatus status)
{
    switch (status) {
    case WheelEventStatus::UserScrollBegin: ts << "UserScrollBegin"; break;
    case WheelEventStatus::UserScrolling: ts << "UserScrolling"; break;
    case WheelEventStatus::UserScrollEnd: ts << "UserScrollEnd"; break;
    case WheelEventStatus::MomentumScrollBegin: ts << "MomentumScrollBegin"; break;
    case WheelEventStatus::MomentumScrolling: ts << "MomentumScrolling"; break;
    case WheelEventStatus::MomentumScrollEnd: ts << "MomentumScrollEnd"; break;
    case WheelEventStatus::StatelessScrollEvent: ts << "StatelessScrollEvent"; break;
    case WheelEventStatus::Unknown: ts << "Unknown"; break;
    }
    return ts;
}
#endif

bool ScrollingEffectsController::shouldOverrideMomentumScrolling() const
{
    if (!usesScrollSnap())
        return false;

    ScrollSnapState scrollSnapState = m_scrollSnapState->currentState();
    return scrollSnapState == ScrollSnapState::Gliding || scrollSnapState == ScrollSnapState::DestinationReached;
}

void ScrollingEffectsController::scheduleStatelessScrollSnap()
{
    stopScrollSnapAnimation();
    if (m_statelessSnapTransitionTimer) {
        m_statelessSnapTransitionTimer->stop();
        m_statelessSnapTransitionTimer = nullptr;
    }
    if (!usesScrollSnap())
        return;

    static const Seconds statelessScrollSnapDelay = 750_ms;
    m_statelessSnapTransitionTimer = m_client.createTimer([this] {
        statelessSnapTransitionTimerFired();
    });
    m_statelessSnapTransitionTimer->startOneShot(statelessScrollSnapDelay);
    startDeferringWheelEventTestCompletion(WheelEventTestMonitor::ScrollSnapInProgress);
}

void ScrollingEffectsController::statelessSnapTransitionTimerFired()
{
    m_statelessSnapTransitionTimer = nullptr;

    if (!usesScrollSnap())
        return;

    if (m_scrollSnapState->transitionToSnapAnimationState(m_client.scrollExtents(), m_client.pageScaleFactor(), m_client.scrollOffset()))
        startScrollSnapAnimation();
}

bool ScrollingEffectsController::processWheelEventForScrollSnap(const PlatformWheelEvent& wheelEvent)
{
    if (!usesScrollSnap())
        return false;

    if (m_scrollSnapState->snapOffsetsForAxis(ScrollEventAxis::Horizontal).isEmpty() && m_scrollSnapState->snapOffsetsForAxis(ScrollEventAxis::Vertical).isEmpty())
        return false;

    auto status = toWheelEventStatus(wheelEvent.phase(), wheelEvent.momentumPhase());

    LOG_WITH_STREAM(ScrollSnap, stream << "ScrollingEffectsController " << this << " processWheelEventForScrollSnap: status " << status);

    bool isMomentumScrolling = false;
    switch (status) {
    case WheelEventStatus::UserScrollBegin:
    case WheelEventStatus::UserScrolling:
        stopScrollSnapAnimation();
        m_scrollSnapState->transitionToUserInteractionState();
        m_scrollingVelocityForScrollSnap = -wheelEvent.scrollingVelocity();
        break;
    case WheelEventStatus::UserScrollEnd:
        if (m_scrollSnapState->transitionToSnapAnimationState(m_client.scrollExtents(), m_client.pageScaleFactor(), m_client.scrollOffset()))
            startScrollSnapAnimation();
        break;
    case WheelEventStatus::MomentumScrollBegin:
        if (m_scrollSnapState->transitionToGlideAnimationState(m_client.scrollExtents(), m_client.pageScaleFactor(), m_client.scrollOffset(), m_scrollingVelocityForScrollSnap, -wheelEvent.delta())) {
            startScrollSnapAnimation();
            isMomentumScrolling = true;
        }
        m_scrollingVelocityForScrollSnap = { };
        break;
    case WheelEventStatus::MomentumScrolling:
    case WheelEventStatus::MomentumScrollEnd:
        isMomentumScrolling = true;
        break;
    case WheelEventStatus::StatelessScrollEvent:
        m_scrollSnapState->transitionToUserInteractionState();
        scheduleStatelessScrollSnap();
        break;
    case WheelEventStatus::Unknown:
        ASSERT_NOT_REACHED();
        break;
    }

    return isMomentumScrolling && shouldOverrideMomentumScrolling();
}

void ScrollingEffectsController::updateGestureInProgressState(const PlatformWheelEvent& wheelEvent)
{
    if (wheelEvent.isGestureStart() || wheelEvent.isTransitioningToMomentumScroll())
        m_inScrollGesture = true;
    else if (wheelEvent.isEndOfNonMomentumScroll() || wheelEvent.isGestureCancel() || wheelEvent.isEndOfMomentumScroll())
        m_inScrollGesture = false;

    updateRubberBandingState();
}

} // namespace WebCore

#endif // PLATFORM(MAC)
