/*
 * Copyright (C) 2020-2022 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.
 */

#include "config.h"
#include "ScrollLatchingController.h"

#if ENABLE(WHEEL_EVENT_LATCHING)

#include "Element.h"
#include "Frame.h"
#include "FrameView.h"
#include "Logging.h"
#include "PlatformWheelEvent.h"
#include "ScrollableArea.h"
#include <wtf/text/TextStream.h>

namespace WebCore {

// See also ScrollTreeLatchingController.cpp
static const Seconds resetLatchedStateTimeout { 100_ms };

ScrollLatchingController::ScrollLatchingController()
    : m_clearLatchingStateTimer(*this, &ScrollLatchingController::clearTimerFired)
{
}

ScrollLatchingController::~ScrollLatchingController() = default;

void ScrollLatchingController::clear()
{
    LOG_WITH_STREAM(ScrollLatching, stream << "ScrollLatchingController::clear()");
    m_cumulativeEventDelta = { };
    m_frameStateStack.clear();
}

// FIXME: This logic is different from ScrollingTreeLatchingController, which simply lets the latching state elapse after 100ms.
void ScrollLatchingController::clearOrScheduleClearIfNeeded(const PlatformWheelEvent& wheelEvent)
{
    if (wheelEvent.shouldResetLatching() || wheelEvent.isNonGestureEvent()) {
        clear();
        LOG_WITH_STREAM(ScrollLatching, stream << "ScrollLatchingController::clearOrScheduleClearingLatchedStateIfNeeded() - event" << wheelEvent << ", resetting latching");
        return;
    }

    if (m_clearLatchingStateTimer.isActive()) {
        // If another wheel event scrolling starts, stop the timer manually, and reset the latched state immediately.
        if (wheelEvent.isGestureStart()) {
            LOG_WITH_STREAM(ScrollLatching, stream << "ScrollLatchingController::clearOrScheduleClearingLatchedStateIfNeeded() - event" << wheelEvent << ", timer pending, another scroll starting");
            clear();
            m_clearLatchingStateTimer.stop();
        } else if (wheelEvent.isTransitioningToMomentumScroll()) {
            // Wheel events machinery is transitioning to momentum scrolling, so no need to reset latched state. Stop the timer.
            m_clearLatchingStateTimer.stop();
        }
        return;
    }

    if (wheelEvent.isEndOfNonMomentumScroll()) {
        LOG_WITH_STREAM(ScrollLatching, stream << "ScrollLatchingController::clearOrScheduleClearingLatchedStateIfNeeded() - event" << wheelEvent << ", scheduling clear timer");
        m_clearLatchingStateTimer.startOneShot(resetLatchedStateTimeout);
    }
}

void ScrollLatchingController::clearTimerFired()
{
    LOG_WITH_STREAM(ScrollLatching, stream << "ScrollLatchingController::clearTimerFired() - clearing state");
    clear();
}

void ScrollLatchingController::receivedWheelEvent(const PlatformWheelEvent& wheelEvent)
{
    clearOrScheduleClearIfNeeded(wheelEvent);

    if (wheelEvent.isGestureStart() || wheelEvent.isNonGestureEvent())
        m_cumulativeEventDelta = wheelEvent.delta();
    else
        m_cumulativeEventDelta += wheelEvent.delta();
}

bool ScrollLatchingController::latchingAllowsScrollingInFrame(const Frame& frame, WeakPtr<ScrollableArea>& latchedScroller) const
{
    if (m_frameStateStack.isEmpty())
        return true;

    if (auto* frameState = stateForFrame(frame)) {
        latchedScroller = frameState->scrollableArea;
        return !!frameState->scrollableArea;
    }
    return false;
}

void ScrollLatchingController::updateAndFetchLatchingStateForFrame(Frame& frame, const PlatformWheelEvent& wheelEvent, RefPtr<Element>& latchedElement, WeakPtr<ScrollableArea>& scrollableArea, bool& isOverWidget)
{
    if (wheelEvent.isGestureStart()) {
        // We can have existing state here because state is cleared on a timer.
        if (!hasStateForFrame(frame)) {
            FrameState state;
            state.frame = &frame;
            state.wheelEventElement = latchedElement;
            if (shouldLatchToScrollableArea(frame, scrollableArea.get(), m_cumulativeEventDelta))
                state.scrollableArea = scrollableArea;
            state.isOverWidget = isOverWidget;

            LOG_WITH_STREAM(ScrollLatching, stream << "ScrollLatchingController::updateAndFetchLatchingStateForFrame() - pushing state for Frame " << &frame << " element " << state.wheelEventElement.get() << " scrollableArea " << state.scrollableArea);
            m_frameStateStack.append(WTFMove(state));
            return;
        }
    }

    if (wheelEvent.isGestureContinuation()) {
        auto* state = stateForFrame(frame);
        if (!state)
            return;

        // We may not have latched at gesture start because of small deltas. Re-evaluate latching based on accumulated delta.
        if (!state->scrollableArea && shouldLatchToScrollableArea(frame, scrollableArea.get(), m_cumulativeEventDelta))
            state->scrollableArea = scrollableArea;
    }

    if (!wheelEvent.useLatchedEventElement())
        return;

    for (const auto& state : m_frameStateStack) {
        if (state.frame == &frame) {
            latchedElement = state.wheelEventElement.get();
            scrollableArea = state.scrollableArea;
            isOverWidget = state.isOverWidget;

            LOG_WITH_STREAM(ScrollLatching, stream << "ScrollLatchingController::updateAndFetchLatchingStateForFrame() - using state for Frame " << &frame << " element " << latchedElement.get() << " scrollableArea " << scrollableArea);
        }
    }
}

void ScrollLatchingController::removeLatchingStateForTarget(const Element& element)
{
    if (m_frameStateStack.isEmpty())
        return;

    auto findResult = m_frameStateStack.findIf([&element] (const auto& state) {
        auto* wheelElement = state.wheelEventElement.get();
        return wheelElement && element.isEqualNode(wheelElement);
    });
    
    // If this element is found in the latching stack, just clear the whole stack. We can't just remove one entry,
    // since the stack has to match the frame hierarchy.
    if (findResult != notFound)
        m_frameStateStack.clear();
}

void ScrollLatchingController::removeLatchingStateForFrame(const Frame& frame)
{
    if (m_frameStateStack.isEmpty())
        return;

    // If the frame was in the latching stack, just clear state.
    if (auto* frameState = stateForFrame(frame))
        clear();
}

static bool deltaIsPredominantlyVertical(FloatSize delta)
{
    return std::abs(delta.height()) > std::abs(delta.width());
}

bool ScrollLatchingController::shouldLatchToScrollableArea(const Frame& frame, ScrollableArea* scrollableArea, FloatSize scrollDelta) const
{
    if (!scrollableArea)
        return false;

    // We always allow the main frame to receive wheel events to permit rubber-banding.
    if (frame.isMainFrame() && scrollableArea == frame.view())
        return true;

    if (!scrollableArea->canHaveScrollbars())
        return false;

    if (scrollDelta.isZero())
        return false;

    if (!deltaIsPredominantlyVertical(scrollDelta) && scrollDelta.width()) {
        if (!scrollableArea->horizontalScrollbar())
            return false;

        if (scrollDelta.width() < 0)
            return !scrollableArea->scrolledToRight();
        
        return !scrollableArea->scrolledToLeft();
    }

    if (!scrollableArea->verticalScrollbar())
        return false;

    if (scrollDelta.height() < 0)
        return !scrollableArea->scrolledToBottom();

    return !scrollableArea->scrolledToTop();
}

bool ScrollLatchingController::hasStateForFrame(const Frame& frame) const
{
    for (const auto& state : m_frameStateStack) {
        if (state.frame == &frame)
            return true;
    }
    return false;
}

ScrollLatchingController::FrameState* ScrollLatchingController::stateForFrame(const Frame& frame)
{
    for (auto& state : m_frameStateStack) {
        if (state.frame == &frame)
            return &state;
    }
    return nullptr;
}

const ScrollLatchingController::FrameState* ScrollLatchingController::stateForFrame(const Frame& frame) const
{
    for (const auto& state : m_frameStateStack) {
        if (state.frame == &frame)
            return &state;
    }
    return nullptr;
}

void ScrollLatchingController::dump(WTF::TextStream& ts) const
{
    TextStream multilineStream;
    multilineStream.setIndent(ts.indent() + 2);

    for (const auto& state : m_frameStateStack) {
        TextStream::GroupScope groupScope(multilineStream);
        multilineStream.dumpProperty("frame", ValueOrNull(state.frame));
        multilineStream.dumpProperty("element", ValueOrNull(state.wheelEventElement.get()));
        multilineStream.dumpProperty("scrollable area", ValueOrNull(state.scrollableArea.get()));
        multilineStream.dumpProperty("is over widget", state.isOverWidget);
    }

    ts << "ScrollLatchingController state " << multilineStream.release();
}

TextStream& operator<<(TextStream& ts, const ScrollLatchingController& controller)
{
    controller.dump(ts);
    return ts;
}

} // namespace WebCore

#endif // ENABLE(WHEEL_EVENT_LATCHING)
