/*
 * Copyright (c) 2010, Google Inc. All rights reserved.
 * Copyright (C) 2008, 2011, 2014-2016 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:
 * 
 *     * 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 "ScrollableArea.h"

#include "FloatPoint.h"
#include "GraphicsContext.h"
#include "GraphicsLayer.h"
#include "LayoutRect.h"
#include "Logging.h"
#include "PlatformWheelEvent.h"
#include "ScrollAnimator.h"
#include "ScrollbarTheme.h"
#include "ScrollbarsControllerMock.h"
#include <wtf/text/TextStream.h>

namespace WebCore {

struct SameSizeAsScrollableArea {
    virtual ~SameSizeAsScrollableArea();
#if ASSERT_ENABLED
    bool weakPtrFactorWasConstructedOnMainThread;
#endif
    void* pointer[3];
    IntPoint origin;
    bool bytes[9];
};

COMPILE_ASSERT(sizeof(ScrollableArea) == sizeof(SameSizeAsScrollableArea), ScrollableArea_should_stay_small);

ScrollableArea::ScrollableArea() = default;
ScrollableArea::~ScrollableArea() = default;

ScrollAnimator& ScrollableArea::scrollAnimator() const
{
    if (!m_scrollAnimator)
        m_scrollAnimator = ScrollAnimator::create(const_cast<ScrollableArea&>(*this));

    return *m_scrollAnimator.get();
}

ScrollbarsController& ScrollableArea::scrollbarsController() const
{
    if (!m_scrollbarsController) {
        if (mockScrollbarsControllerEnabled()) {
            m_scrollbarsController = makeUnique<ScrollbarsControllerMock>(const_cast<ScrollableArea&>(*this), [this](const String& message) {
                logMockScrollbarsControllerMessage(message);
            });
        } else
            m_scrollbarsController = ScrollbarsController::create(const_cast<ScrollableArea&>(*this));
    }

    return *m_scrollbarsController.get();
}

void ScrollableArea::setScrollOrigin(const IntPoint& origin)
{
    if (m_scrollOrigin != origin) {
        m_scrollOrigin = origin;
        m_scrollOriginChanged = true;
    }
}

float ScrollableArea::adjustVerticalPageScrollStepForFixedContent(float step)
{
    return step;
}

bool ScrollableArea::scroll(ScrollDirection direction, ScrollGranularity granularity, unsigned stepCount)
{
    auto* scrollbar = scrollbarForDirection(direction);
    if (!scrollbar)
        return false;

    float step = 0;
    switch (granularity) {
    case ScrollGranularity::Line:
        step = scrollbar->lineStep();
        break;
    case ScrollGranularity::Page:
        step = scrollbar->pageStep();
        break;
    case ScrollGranularity::Document:
        step = scrollbar->totalSize();
        break;
    case ScrollGranularity::Pixel:
        step = scrollbar->pixelStep();
        break;
    }

    auto axis = axisFromDirection(direction);

    if (granularity == ScrollGranularity::Page && axis == ScrollEventAxis::Vertical)
        step = adjustVerticalPageScrollStepForFixedContent(step);

    auto scrollDelta = step * stepCount;
    
    if (direction == ScrollUp || direction == ScrollLeft)
        scrollDelta = -scrollDelta;

    return scrollAnimator().singleAxisScroll(axis, scrollDelta, ScrollAnimator::ScrollBehavior::RespectScrollSnap);
}

void ScrollableArea::scrollToPositionWithoutAnimation(const FloatPoint& position, ScrollClamping clamping)
{
    LOG_WITH_STREAM(Scrolling, stream << "ScrollableArea " << this << " scrollToPositionWithoutAnimation " << position);
    scrollAnimator().scrollToPositionWithoutAnimation(position, clamping);
}

void ScrollableArea::scrollToPositionWithAnimation(const FloatPoint& position, ScrollClamping clamping)
{
    LOG_WITH_STREAM(Scrolling, stream << "ScrollableArea " << this << " scrollToPositionWithAnimation " << position);

    bool startedAnimation = requestAnimatedScrollToPosition(roundedIntPoint(position), clamping);
    if (!startedAnimation)
        startedAnimation = scrollAnimator().scrollToPositionWithAnimation(position, clamping);

    if (startedAnimation)
        setScrollAnimationStatus(ScrollAnimationStatus::Animating);
}

void ScrollableArea::scrollToOffsetWithoutAnimation(const FloatPoint& offset, ScrollClamping clamping)
{
    LOG_WITH_STREAM(Scrolling, stream << "ScrollableArea " << this << " scrollToOffsetWithoutAnimation " << offset);

    auto position = scrollPositionFromOffset(offset, toFloatSize(scrollOrigin()));
    scrollAnimator().scrollToPositionWithoutAnimation(position, clamping);
}

void ScrollableArea::scrollToOffsetWithoutAnimation(ScrollbarOrientation orientation, float offset)
{
    auto currentPosition = scrollAnimator().currentPosition();
    if (orientation == ScrollbarOrientation::Horizontal)
        scrollAnimator().scrollToPositionWithoutAnimation(FloatPoint(offset, currentPosition.y()));
    else
        scrollAnimator().scrollToPositionWithoutAnimation(FloatPoint(currentPosition.x(), offset));
}

void ScrollableArea::notifyScrollPositionChanged(const ScrollPosition& position)
{
    scrollPositionChanged(position);
    scrollAnimator().setCurrentPosition(position);
}

void ScrollableArea::scrollPositionChanged(const ScrollPosition& position)
{
    IntPoint oldPosition = scrollPosition();
    // Tell the derived class to scroll its contents.
    setScrollOffset(scrollOffsetFromPosition(position));

    auto* verticalScrollbar = this->verticalScrollbar();

    // Tell the scrollbars to update their thumb postions.
    if (auto* horizontalScrollbar = this->horizontalScrollbar()) {
        horizontalScrollbar->offsetDidChange();
        if (horizontalScrollbar->isOverlayScrollbar() && !hasLayerForHorizontalScrollbar()) {
            if (!verticalScrollbar)
                horizontalScrollbar->invalidate();
            else {
                // If there is both a horizontalScrollbar and a verticalScrollbar,
                // then we must also invalidate the corner between them.
                IntRect boundsAndCorner = horizontalScrollbar->boundsRect();
                boundsAndCorner.setWidth(boundsAndCorner.width() + verticalScrollbar->width());
                horizontalScrollbar->invalidateRect(boundsAndCorner);
            }
        }
    }
    if (verticalScrollbar) {
        verticalScrollbar->offsetDidChange();
        if (verticalScrollbar->isOverlayScrollbar() && !hasLayerForVerticalScrollbar())
            verticalScrollbar->invalidate();
    }

    if (scrollPosition() != oldPosition)
        scrollbarsController().notifyContentAreaScrolled(scrollPosition() - oldPosition);
}

bool ScrollableArea::handleWheelEventForScrolling(const PlatformWheelEvent& wheelEvent, std::optional<WheelScrollGestureState>)
{
    if (!isScrollableOrRubberbandable())
        return false;

    bool handledEvent = scrollAnimator().handleWheelEvent(wheelEvent);
    
    LOG_WITH_STREAM(Scrolling, stream << "ScrollableArea (" << *this << ") handleWheelEvent - handled " << handledEvent);
    return handledEvent;
}

void ScrollableArea::stopKeyboardScrollAnimation()
{
    scrollAnimator().stopKeyboardScrollAnimation();
}

#if ENABLE(TOUCH_EVENTS)
bool ScrollableArea::handleTouchEvent(const PlatformTouchEvent& touchEvent)
{
    return scrollAnimator().handleTouchEvent(touchEvent);
}
#endif

// NOTE: Only called from Internals for testing.
void ScrollableArea::setScrollOffsetFromInternals(const ScrollOffset& offset)
{
    setScrollPositionFromAnimation(scrollPositionFromOffset(offset));
}

void ScrollableArea::setScrollPositionFromAnimation(const ScrollPosition& position)
{
    // An early return here if the position hasn't changed breaks an iOS RTL scrolling test: webkit.org/b/230450.
    auto scrollType = currentScrollType();
    auto clamping = scrollType == ScrollType::User ? ScrollClamping::Unclamped : ScrollClamping::Clamped;
    if (requestScrollPositionUpdate(position, scrollType, clamping))
        return;

    scrollPositionChanged(position);
}

void ScrollableArea::willStartLiveResize()
{
    if (m_inLiveResize)
        return;

    m_inLiveResize = true;
    scrollbarsController().willStartLiveResize();
}

void ScrollableArea::willEndLiveResize()
{
    if (!m_inLiveResize)
        return;

    m_inLiveResize = false;
    scrollbarsController().willEndLiveResize();
    scrollAnimator().contentsSizeChanged();
}

void ScrollableArea::contentAreaWillPaint() const
{
    // This is used to flash overlay scrollbars in some circumstances.
    scrollbarsController().contentAreaWillPaint();
}

void ScrollableArea::mouseEnteredContentArea() const
{
    scrollbarsController().mouseEnteredContentArea();
}

void ScrollableArea::mouseExitedContentArea() const
{
    scrollbarsController().mouseExitedContentArea();
}

void ScrollableArea::mouseMovedInContentArea() const
{
    scrollbarsController().mouseMovedInContentArea();
}

void ScrollableArea::mouseEnteredScrollbar(Scrollbar* scrollbar) const
{
    scrollbarsController().mouseEnteredScrollbar(scrollbar);
}

void ScrollableArea::mouseExitedScrollbar(Scrollbar* scrollbar) const
{
    scrollbarsController().mouseExitedScrollbar(scrollbar);
}

void ScrollableArea::mouseIsDownInScrollbar(Scrollbar* scrollbar, bool mouseIsDown) const
{
    scrollbarsController().mouseIsDownInScrollbar(scrollbar, mouseIsDown);
}

void ScrollableArea::contentAreaDidShow() const
{
    scrollbarsController().contentAreaDidShow();
}

void ScrollableArea::contentAreaDidHide() const
{
    scrollbarsController().contentAreaDidHide();
}

void ScrollableArea::lockOverlayScrollbarStateToHidden(bool shouldLockState) const
{
    scrollbarsController().lockOverlayScrollbarStateToHidden(shouldLockState);
}

bool ScrollableArea::scrollbarsCanBeActive() const
{
    return scrollbarsController().scrollbarsCanBeActive();
}

void ScrollableArea::didAddScrollbar(Scrollbar* scrollbar, ScrollbarOrientation orientation)
{
    if (orientation == ScrollbarOrientation::Vertical)
        scrollbarsController().didAddVerticalScrollbar(scrollbar);
    else
        scrollbarsController().didAddHorizontalScrollbar(scrollbar);

    scrollAnimator().contentsSizeChanged();

    // <rdar://problem/9797253> AppKit resets the scrollbar's style when you attach a scrollbar
    setScrollbarOverlayStyle(scrollbarOverlayStyle());
}

void ScrollableArea::willRemoveScrollbar(Scrollbar* scrollbar, ScrollbarOrientation orientation)
{
    if (orientation == ScrollbarOrientation::Vertical)
        scrollbarsController().willRemoveVerticalScrollbar(scrollbar);
    else
        scrollbarsController().willRemoveHorizontalScrollbar(scrollbar);
}

void ScrollableArea::contentsResized()
{
    scrollAnimator().contentsSizeChanged();
    scrollbarsController().contentsSizeChanged();
}

void ScrollableArea::availableContentSizeChanged(AvailableSizeChangeReason)
{
    scrollAnimator().contentsSizeChanged();
    scrollbarsController().contentsSizeChanged(); // This flashes overlay scrollbars.
}

bool ScrollableArea::hasOverlayScrollbars() const
{
    return (verticalScrollbar() && verticalScrollbar()->isOverlayScrollbar())
        || (horizontalScrollbar() && horizontalScrollbar()->isOverlayScrollbar());
}

void ScrollableArea::setScrollbarOverlayStyle(ScrollbarOverlayStyle overlayStyle)
{
    m_scrollbarOverlayStyle = overlayStyle;

    if (auto* scrollbar = horizontalScrollbar())
        ScrollbarTheme::theme().updateScrollbarOverlayStyle(*scrollbar);

    if (auto* scrollbar = verticalScrollbar())
        ScrollbarTheme::theme().updateScrollbarOverlayStyle(*scrollbar);

    invalidateScrollbars();
}

void ScrollableArea::invalidateScrollbars()
{
    if (auto* scrollbar = horizontalScrollbar()) {
        scrollbar->invalidate();
        scrollbarsController().invalidateScrollbarPartLayers(scrollbar);
    }

    if (auto* scrollbar = verticalScrollbar()) {
        scrollbar->invalidate();
        scrollbarsController().invalidateScrollbarPartLayers(scrollbar);
    }
}

bool ScrollableArea::useDarkAppearanceForScrollbars() const
{
    // If dark appearance is used or the overlay style is light (because of a dark page background), set the dark appearance.
    return useDarkAppearance() || scrollbarOverlayStyle() == WebCore::ScrollbarOverlayStyleLight;
}

void ScrollableArea::invalidateScrollbar(Scrollbar& scrollbar, const IntRect& rect)
{
    if (&scrollbar == horizontalScrollbar()) {
        if (GraphicsLayer* graphicsLayer = layerForHorizontalScrollbar()) {
            graphicsLayer->setNeedsDisplay();
            graphicsLayer->setContentsNeedsDisplay();
            return;
        }
    } else if (&scrollbar == verticalScrollbar()) {
        if (GraphicsLayer* graphicsLayer = layerForVerticalScrollbar()) {
            graphicsLayer->setNeedsDisplay();
            graphicsLayer->setContentsNeedsDisplay();
            return;
        }
    }

    invalidateScrollbarRect(scrollbar, rect);
}

void ScrollableArea::invalidateScrollCorner(const IntRect& rect)
{
    if (GraphicsLayer* graphicsLayer = layerForScrollCorner()) {
        graphicsLayer->setNeedsDisplay();
        return;
    }

    invalidateScrollCornerRect(rect);
}

void ScrollableArea::verticalScrollbarLayerDidChange()
{
    scrollbarsController().verticalScrollbarLayerDidChange();
}

void ScrollableArea::horizontalScrollbarLayerDidChange()
{
    scrollbarsController().horizontalScrollbarLayerDidChange();
}

bool ScrollableArea::hasLayerForHorizontalScrollbar() const
{
    return layerForHorizontalScrollbar();
}

bool ScrollableArea::hasLayerForVerticalScrollbar() const
{
    return layerForVerticalScrollbar();
}

bool ScrollableArea::hasLayerForScrollCorner() const
{
    return layerForScrollCorner();
}

bool ScrollableArea::allowsHorizontalScrolling() const
{
    auto* horizontalScrollbar = this->horizontalScrollbar();
    return horizontalScrollbar && horizontalScrollbar->enabled();
}

bool ScrollableArea::allowsVerticalScrolling() const
{
    auto* verticalScrollbar = this->verticalScrollbar();
    return verticalScrollbar && verticalScrollbar->enabled();
}

String ScrollableArea::horizontalScrollbarStateForTesting() const
{
    return scrollbarsController().horizontalScrollbarStateForTesting();
}

String ScrollableArea::verticalScrollbarStateForTesting() const
{
    return scrollbarsController().verticalScrollbarStateForTesting();
}

const LayoutScrollSnapOffsetsInfo* ScrollableArea::snapOffsetsInfo() const
{
    return existingScrollAnimator() ? existingScrollAnimator()->snapOffsetsInfo() : nullptr;
}

void ScrollableArea::setScrollSnapOffsetInfo(const LayoutScrollSnapOffsetsInfo& info)
{
    if (info.isEmpty()) {
        clearSnapOffsets();
        return;
    }

    // Consider having a non-empty set of snap offsets as a cue to initialize the ScrollAnimator.
    scrollAnimator().setSnapOffsetsInfo(info);
}

void ScrollableArea::clearSnapOffsets()
{
    if (auto* scrollAnimator = existingScrollAnimator())
        return scrollAnimator->setSnapOffsetsInfo(LayoutScrollSnapOffsetsInfo());
}

std::optional<unsigned> ScrollableArea::currentHorizontalSnapPointIndex() const
{
    if (auto* scrollAnimator = existingScrollAnimator())
        return scrollAnimator->activeScrollSnapIndexForAxis(ScrollEventAxis::Horizontal);
    return std::nullopt;
}

std::optional<unsigned> ScrollableArea::currentVerticalSnapPointIndex() const
{
    if (auto* scrollAnimator = existingScrollAnimator())
        return scrollAnimator->activeScrollSnapIndexForAxis(ScrollEventAxis::Vertical);
    return std::nullopt;
}

void ScrollableArea::setCurrentHorizontalSnapPointIndex(std::optional<unsigned> index)
{
    scrollAnimator().setActiveScrollSnapIndexForAxis(ScrollEventAxis::Horizontal, index);
}

void ScrollableArea::setCurrentVerticalSnapPointIndex(std::optional<unsigned> index)
{
    scrollAnimator().setActiveScrollSnapIndexForAxis(ScrollEventAxis::Vertical, index);
}

void ScrollableArea::resnapAfterLayout()
{
    LOG_WITH_STREAM(ScrollSnap, stream << *this << " updateScrollSnapState: isScrollSnapInProgress " << isScrollSnapInProgress() << " isUserScrollInProgress " << isUserScrollInProgress());

    auto* scrollAnimator = existingScrollAnimator();
    if (!scrollAnimator || isScrollSnapInProgress() || isUserScrollInProgress())
        return;

    scrollAnimator->resnapAfterLayout();

    const auto* info = snapOffsetsInfo();
    if (!info)
        return;

    auto currentOffset = scrollOffset();
    auto correctedOffset = currentOffset;

    if (!horizontalScrollbar() || horizontalScrollbar()->pressedPart() == ScrollbarPart::NoPart) {
        const auto& horizontal = info->horizontalSnapOffsets;
        auto activeHorizontalIndex = currentHorizontalSnapPointIndex();
        if (activeHorizontalIndex)
            correctedOffset.setX(horizontal[*activeHorizontalIndex].offset.toInt());
    }

    if (!verticalScrollbar() || verticalScrollbar()->pressedPart() == ScrollbarPart::NoPart) {
        const auto& vertical = info->verticalSnapOffsets;
        auto activeVerticalIndex = currentVerticalSnapPointIndex();
        if (activeVerticalIndex)
            correctedOffset.setY(vertical[*activeVerticalIndex].offset.toInt());
    }

    if (correctedOffset != currentOffset) {
        LOG_WITH_STREAM(ScrollSnap, stream << " adjusting offset from " << currentOffset << " to " << correctedOffset);
        auto position = scrollPositionFromOffset(correctedOffset);
        if (scrollAnimationStatus() == ScrollAnimationStatus::NotAnimating)
            scrollToOffsetWithoutAnimation(correctedOffset);
        else
            scrollAnimator->retargetRunningAnimation(position);
    }
}

void ScrollableArea::doPostThumbMoveSnapping(ScrollbarOrientation orientation)
{
    auto* scrollAnimator = existingScrollAnimator();
    if (!scrollAnimator)
        return;

    auto currentOffset = scrollOffset();
    auto newOffset = currentOffset;
    if (orientation == ScrollbarOrientation::Horizontal)
        newOffset.setX(scrollAnimator->scrollOffsetAdjustedForSnapping(ScrollEventAxis::Horizontal, currentOffset, ScrollSnapPointSelectionMethod::Closest));
    else
        newOffset.setY(scrollAnimator->scrollOffsetAdjustedForSnapping(ScrollEventAxis::Vertical, currentOffset, ScrollSnapPointSelectionMethod::Closest));

    if (newOffset == currentOffset)
        return;

    auto position = scrollPositionFromOffset(newOffset);
    scrollAnimator->scrollToPositionWithAnimation(position);
}

bool ScrollableArea::isPinnedOnSide(BoxSide side) const
{
    switch (side) {
    case BoxSide::Top:
        if (!allowsVerticalScrolling())
            return true;
        return scrollPosition().y() <= minimumScrollPosition().y();
    case BoxSide::Bottom:
        if (!allowsVerticalScrolling())
            return true;
        return scrollPosition().y() >= maximumScrollPosition().y();
    case BoxSide::Left:
        if (!allowsHorizontalScrolling())
            return true;
        return scrollPosition().x() <= minimumScrollPosition().x();
    case BoxSide::Right:
        if (!allowsHorizontalScrolling())
            return true;
        return scrollPosition().x() >= maximumScrollPosition().x();
    }
    return false;
}

RectEdges<bool> ScrollableArea::edgePinnedState() const
{
    auto scrollPosition = this->scrollPosition();
    auto minScrollPosition = minimumScrollPosition();
    auto maxScrollPosition = maximumScrollPosition();

    bool horizontallyUnscrollable = !allowsHorizontalScrolling();
    bool verticallyUnscrollable = !allowsVerticalScrolling();

    // Top, right, bottom, left.
    return {
        verticallyUnscrollable || scrollPosition.y() <= minScrollPosition.y(),
        horizontallyUnscrollable || scrollPosition.x() >= maxScrollPosition.x(),
        verticallyUnscrollable || scrollPosition.y() >= maxScrollPosition.y(),
        horizontallyUnscrollable || scrollPosition.x() <= minScrollPosition.x()
    };
}

int ScrollableArea::horizontalScrollbarIntrusion() const
{
    return verticalScrollbar() ? verticalScrollbar()->occupiedWidth() : 0;
}

int ScrollableArea::verticalScrollbarIntrusion() const
{
    return horizontalScrollbar() ? horizontalScrollbar()->occupiedHeight() : 0;
}

IntSize ScrollableArea::scrollbarIntrusion() const
{
    return { horizontalScrollbarIntrusion(), verticalScrollbarIntrusion() };
}

ScrollOffset ScrollableArea::scrollOffset() const
{
    return scrollOffsetFromPosition(scrollPosition());
}

ScrollPosition ScrollableArea::minimumScrollPosition() const
{
    return scrollPositionFromOffset(ScrollPosition());
}

ScrollPosition ScrollableArea::maximumScrollPosition() const
{
    return scrollPositionFromOffset(ScrollPosition(totalContentsSize() - visibleSize()));
}

ScrollOffset ScrollableArea::maximumScrollOffset() const
{
    return ScrollOffset(totalContentsSize() - visibleSize());
}

ScrollPosition ScrollableArea::scrollPositionFromOffset(ScrollOffset offset) const
{
    return scrollPositionFromOffset(offset, toIntSize(m_scrollOrigin));
}

ScrollOffset ScrollableArea::scrollOffsetFromPosition(ScrollPosition position) const
{
    return scrollOffsetFromPosition(position, toIntSize(m_scrollOrigin));
}

bool ScrollableArea::scrolledToTop() const
{
    return scrollPosition().y() <= minimumScrollPosition().y();
}

bool ScrollableArea::scrolledToBottom() const
{
    return scrollPosition().y() >= maximumScrollPosition().y();
}

bool ScrollableArea::scrolledToLeft() const
{
    return scrollPosition().x() <= minimumScrollPosition().x();
}

bool ScrollableArea::scrolledToRight() const
{
    return scrollPosition().x() >= maximumScrollPosition().x();
}

void ScrollableArea::scrollbarStyleChanged(ScrollbarStyle, bool)
{
    availableContentSizeChanged(AvailableSizeChangeReason::ScrollbarsChanged);
}

IntSize ScrollableArea::reachableTotalContentsSize() const
{
    return totalContentsSize();
}

IntSize ScrollableArea::totalContentsSize() const
{
    IntSize totalContentsSize = contentsSize();
    totalContentsSize.setHeight(totalContentsSize.height() + headerHeight() + footerHeight());
    return totalContentsSize;
}

IntRect ScrollableArea::visibleContentRect(VisibleContentRectBehavior visibleContentRectBehavior) const
{
    return visibleContentRectInternal(ExcludeScrollbars, visibleContentRectBehavior);
}

IntRect ScrollableArea::visibleContentRectIncludingScrollbars(VisibleContentRectBehavior visibleContentRectBehavior) const
{
    return visibleContentRectInternal(IncludeScrollbars, visibleContentRectBehavior);
}

IntRect ScrollableArea::visibleContentRectInternal(VisibleContentRectIncludesScrollbars scrollbarInclusion, VisibleContentRectBehavior) const
{
    int verticalScrollbarWidth = 0;
    int horizontalScrollbarHeight = 0;

    if (scrollbarInclusion == IncludeScrollbars) {
        if (Scrollbar* verticalBar = verticalScrollbar())
            verticalScrollbarWidth = verticalBar->occupiedWidth();
        if (Scrollbar* horizontalBar = horizontalScrollbar())
            horizontalScrollbarHeight = horizontalBar->occupiedHeight();
    }

    return IntRect(scrollPosition().x(),
                   scrollPosition().y(),
                   std::max(0, visibleWidth() + verticalScrollbarWidth),
                   std::max(0, visibleHeight() + horizontalScrollbarHeight));
}

LayoutPoint ScrollableArea::constrainScrollPositionForOverhang(const LayoutRect& visibleContentRect, const LayoutSize& totalContentsSize, const LayoutPoint& scrollPosition, const LayoutPoint& scrollOrigin, int headerHeight, int footerHeight)
{
    // The viewport rect that we're scrolling shouldn't be larger than our document.
    LayoutSize idealScrollRectSize(std::min(visibleContentRect.width(), totalContentsSize.width()), std::min(visibleContentRect.height(), totalContentsSize.height()));
    
    LayoutRect scrollRect(scrollPosition + scrollOrigin - LayoutSize(0, headerHeight), idealScrollRectSize);
    LayoutRect documentRect(LayoutPoint(), LayoutSize(totalContentsSize.width(), totalContentsSize.height() - headerHeight - footerHeight));

    // Use intersection to constrain our ideal scroll rect by the document rect.
    scrollRect.intersect(documentRect);

    if (scrollRect.size() != idealScrollRectSize) {
        // If the rect was clipped, restore its size, effectively pushing it "down" from the top left.
        scrollRect.setSize(idealScrollRectSize);

        // If we still clip, push our rect "up" from the bottom right.
        scrollRect.intersect(documentRect);
        if (scrollRect.width() < idealScrollRectSize.width())
            scrollRect.move(-(idealScrollRectSize.width() - scrollRect.width()), 0_lu);
        if (scrollRect.height() < idealScrollRectSize.height())
            scrollRect.move(0_lu, -(idealScrollRectSize.height() - scrollRect.height()));
    }

    return scrollRect.location() - toLayoutSize(scrollOrigin);
}

LayoutPoint ScrollableArea::constrainScrollPositionForOverhang(const LayoutPoint& scrollPosition)
{
    return constrainScrollPositionForOverhang(visibleContentRect(), totalContentsSize(), scrollPosition, scrollOrigin(), headerHeight(), footerHeight());
}

void ScrollableArea::computeScrollbarValueAndOverhang(float currentPosition, float totalSize, float visibleSize, float& doubleValue, float& overhangAmount)
{
    doubleValue = 0;
    overhangAmount = 0;
    float maximum = totalSize - visibleSize;

    if (currentPosition < 0) {
        // Scrolled past the top.
        doubleValue = 0;
        overhangAmount = -currentPosition;
    } else if (visibleSize + currentPosition > totalSize) {
        // Scrolled past the bottom.
        doubleValue = 1;
        overhangAmount = currentPosition + visibleSize - totalSize;
    } else {
        // Within the bounds of the scrollable area.
        if (maximum > 0)
            doubleValue = currentPosition / maximum;
        else
            doubleValue = 0;
    }
}

std::optional<BoxSide> ScrollableArea::targetSideForScrollDelta(FloatSize delta, ScrollEventAxis axis)
{
    switch (axis) {
    case ScrollEventAxis::Horizontal:
        if (delta.width() < 0)
            return BoxSide::Left;

        if (delta.width() > 0)
            return BoxSide::Right;
        break;

    case ScrollEventAxis::Vertical:
        if (delta.height() < 0)
            return BoxSide::Top;

        if (delta.height() > 0)
            return BoxSide::Bottom;
        break;
    }

    return { };
}

TextStream& operator<<(TextStream& ts, const ScrollableArea& scrollableArea)
{
    ts << scrollableArea.debugDescription();
    return ts;
}

} // namespace WebCore
