/*
 * Copyright (C) 2006-2018 Apple Inc. All rights reserved.
 *               2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
 *
 * 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. 
 * 3.  Neither the name of Apple Inc. ("Apple") 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 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 "RenderListBox.h"

#include "AXObjectCache.h"
#include "CSSFontSelector.h"
#include "DeprecatedGlobalSettings.h"
#include "DocumentInlines.h"
#include "EventHandler.h"
#include "FocusController.h"
#include "Frame.h"
#include "FrameSelection.h"
#include "FrameView.h"
#include "GraphicsContext.h"
#include "HTMLNames.h"
#include "HTMLOptionElement.h"
#include "HTMLOptGroupElement.h"
#include "HTMLSelectElement.h"
#include "HitTestResult.h"
#include "NodeRenderStyle.h"
#include "Page.h"
#include "PaintInfo.h"
#include "RenderLayer.h"
#include "RenderLayerScrollableArea.h"
#include "RenderLayoutState.h"
#include "RenderScrollbar.h"
#include "RenderText.h"
#include "RenderTheme.h"
#include "RenderView.h"
#include "ScrollAnimator.h"
#include "Scrollbar.h"
#include "ScrollbarTheme.h"
#include "Settings.h"
#include "SpatialNavigation.h"
#include "StyleResolver.h"
#include "StyleTreeResolver.h"
#include "WheelEventTestMonitor.h"
#include <math.h>
#include <wtf/IsoMallocInlines.h>
#include <wtf/StackStats.h>

namespace WebCore {

using namespace HTMLNames;

WTF_MAKE_ISO_ALLOCATED_IMPL(RenderListBox);
 
const int rowSpacing = 1;

const int optionsSpacingHorizontal = 2;

// The minSize constant was originally defined to render scrollbars correctly.
// This might vary for different platforms.
const int minSize = 4;

// Default size when the multiple attribute is present but size attribute is absent.
const int defaultSize = 4;

// FIXME: This hardcoded baselineAdjustment is what we used to do for the old
// widget, but I'm not sure this is right for the new control.
const int baselineAdjustment = 7;

RenderListBox::RenderListBox(HTMLSelectElement& element, RenderStyle&& style)
    : RenderBlockFlow(element, WTFMove(style))
{
    view().frameView().addScrollableArea(this);
}

RenderListBox::~RenderListBox()
{
    // Do not add any code here. Add it to willBeDestroyed() instead.
}

void RenderListBox::willBeDestroyed()
{
    setHasVerticalScrollbar(false);
    view().frameView().removeScrollableArea(this);
    RenderBlockFlow::willBeDestroyed();
}

HTMLSelectElement& RenderListBox::selectElement() const
{
    return downcast<HTMLSelectElement>(nodeForNonAnonymous());
}

static FontCascade bolder(Document& document, const FontCascade& font)
{
    auto description = font.fontDescription();
    description.setWeight(description.bolderWeight());
    auto result = FontCascade { WTFMove(description), font.letterSpacing(), font.wordSpacing() };
    result.update(&document.fontSelector());
    return result;
}

void RenderListBox::updateFromElement()
{
    if (m_optionsChanged) {
        float width = 0;
        auto& normalFont = style().fontCascade();
        std::optional<FontCascade> boldFont;
        for (auto* element : selectElement().listItems()) {
            String text;
            Function<const FontCascade&()> selectFont = [&normalFont] () -> const FontCascade& {
                return normalFont;
            };
            if (is<HTMLOptionElement>(*element))
                text = downcast<HTMLOptionElement>(*element).textIndentedToRespectGroupLabel();
            else if (is<HTMLOptGroupElement>(*element)) {
                text = downcast<HTMLOptGroupElement>(*element).groupLabelText();
                selectFont = [this, &normalFont, &boldFont] () -> const FontCascade& {
                    if (!boldFont)
                        boldFont = bolder(document(), normalFont);
                    return boldFont.value();
                };
            }
            if (text.isEmpty())
                continue;
            text = applyTextTransform(style(), text, ' ');
            auto textRun = constructTextRun(text, style(), ExpansionBehavior::allowRightOnly());
            width = std::max(width, selectFont().width(textRun));
        }
        // FIXME: Is ceiling right here, or should we be doing some kind of rounding instead?
        m_optionsWidth = static_cast<int>(std::ceil(width));
        m_optionsChanged = false;

        setHasVerticalScrollbar(true);

        computeFirstIndexesVisibleInPaddingTopBottomAreas();

        setNeedsLayoutAndPrefWidthsRecalc();
    }
}

void RenderListBox::selectionChanged()
{
    repaint();
    if (!m_inAutoscroll) {
        if (m_optionsChanged || needsLayout())
            m_scrollToRevealSelectionAfterLayout = true;
        else
            scrollToRevealSelection();
    }
    
    if (AXObjectCache* cache = document().existingAXObjectCache())
        cache->deferSelectedChildrenChangedIfNeeded(selectElement());
}

void RenderListBox::layout()
{
    StackStats::LayoutCheckPoint layoutCheckPoint;
    RenderBlockFlow::layout();

    if (m_vBar) {
        bool enabled = numVisibleItems() < numItems();
        m_vBar->setEnabled(enabled);
        m_vBar->setSteps(1, std::max(1, numVisibleItems() - 1), itemHeight());
        m_vBar->setProportion(numVisibleItems(), numItems());
        if (!enabled) {
            scrollToOffsetWithoutAnimation(ScrollbarOrientation::Vertical, 0);
            m_indexOffset = 0;
        }
    }

    if (m_scrollToRevealSelectionAfterLayout) {
        LayoutStateDisabler layoutStateDisabler(view().frameView().layoutContext());
        scrollToRevealSelection();
    }
}

void RenderListBox::scrollToRevealSelection()
{    
    m_scrollToRevealSelectionAfterLayout = false;

    int firstIndex = selectElement().activeSelectionStartListIndex();
    if (firstIndex >= 0 && !listIndexIsVisible(selectElement().activeSelectionEndListIndex()))
        scrollToRevealElementAtListIndex(firstIndex);
}

void RenderListBox::computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const
{
    maxLogicalWidth = shouldApplySizeContainment() ? 2 * optionsSpacingHorizontal : m_optionsWidth + 2 * optionsSpacingHorizontal;
    if (m_vBar)
        maxLogicalWidth += m_vBar->width();
    if (!style().width().isPercentOrCalculated())
        minLogicalWidth = maxLogicalWidth;
}

void RenderListBox::computePreferredLogicalWidths()
{
    // Nested style recal do not fire post recal callbacks. see webkit.org/b/153767
    ASSERT(!m_optionsChanged || Style::postResolutionCallbacksAreSuspended());

    m_minPreferredLogicalWidth = 0;
    m_maxPreferredLogicalWidth = 0;

    if (style().width().isFixed() && style().width().value() > 0)
        m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = adjustContentBoxLogicalWidthForBoxSizing(style().width());
    else
        computeIntrinsicLogicalWidths(m_minPreferredLogicalWidth, m_maxPreferredLogicalWidth);

    RenderBox::computePreferredLogicalWidths(style().minWidth(), style().maxWidth(), horizontalBorderAndPaddingExtent());

    setPreferredLogicalWidthsDirty(false);
}

int RenderListBox::size() const
{
    int specifiedSize = selectElement().size();
    if (specifiedSize > 1)
        return std::max(minSize, specifiedSize);

    return defaultSize;
}

int RenderListBox::numVisibleItems(ConsiderPadding considerPadding) const
{
    // Only count fully visible rows. But don't return 0 even if only part of a row shows.
    int visibleItemsExcludingPadding = std::max<int>(1, (contentHeight() + rowSpacing) / itemHeight());
    if (considerPadding == ConsiderPadding::No)
        return visibleItemsExcludingPadding;

    return numberOfVisibleItemsInPaddingTop() + visibleItemsExcludingPadding + numberOfVisibleItemsInPaddingBottom();
}

int RenderListBox::numItems() const
{
    return selectElement().listItems().size();
}

LayoutUnit RenderListBox::listHeight() const
{
    return itemHeight() * numItems() - rowSpacing;
}

RenderBox::LogicalExtentComputedValues RenderListBox::computeLogicalHeight(LayoutUnit, LayoutUnit logicalTop) const
{
    LayoutUnit height = itemHeight() * size() - rowSpacing;
    cacheIntrinsicContentLogicalHeightForFlexItem(height);
    height += verticalBorderAndPaddingExtent();
    return RenderBox::computeLogicalHeight(height, logicalTop);
}

LayoutUnit RenderListBox::baselinePosition(FontBaseline baselineType, bool firstLine, LineDirectionMode lineDirection, LinePositionMode linePositionMode) const
{
    auto baseline = RenderBox::baselinePosition(baselineType, firstLine, lineDirection, linePositionMode);
    if (!shouldApplyLayoutContainment())
        baseline -= baselineAdjustment;
    return baseline;
}

LayoutRect RenderListBox::itemBoundingBoxRect(const LayoutPoint& additionalOffset, int index)
{
    LayoutUnit x = additionalOffset.x() + borderLeft() + paddingLeft();
    if (shouldPlaceVerticalScrollbarOnLeft() && m_vBar)
        x += m_vBar->occupiedWidth();
    LayoutUnit y = additionalOffset.y() + borderTop() + paddingTop() + itemHeight() * (index - m_indexOffset);
    return LayoutRect(x, y, contentWidth(), itemHeight());
}

void RenderListBox::paintItem(PaintInfo& paintInfo, const LayoutPoint& paintOffset, const PaintFunction& paintFunction)
{
    int listItemsSize = numItems();
    int firstVisibleItem = m_indexOfFirstVisibleItemInsidePaddingTopArea.value_or(m_indexOffset);
    int endIndex = firstVisibleItem + numVisibleItems(ConsiderPadding::Yes);
    for (int i = firstVisibleItem; i < listItemsSize && i < endIndex; ++i)
        paintFunction(paintInfo, paintOffset, i);
}

void RenderListBox::paintObject(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
    if (style().visibility() != Visibility::Visible)
        return;
    
    if (paintInfo.phase == PaintPhase::Foreground) {
        paintItem(paintInfo, paintOffset, [this](PaintInfo& paintInfo, const LayoutPoint& paintOffset, int listItemIndex) {
            paintItemForeground(paintInfo, paintOffset, listItemIndex);
        });
    }

    // Paint the children.
    RenderBlockFlow::paintObject(paintInfo, paintOffset);

    switch (paintInfo.phase) {
    // Depending on whether we have overlay scrollbars they
    // get rendered in the foreground or background phases
    case PaintPhase::Foreground:
        if (m_vBar->isOverlayScrollbar())
            paintScrollbar(paintInfo, paintOffset);
        break;
    case PaintPhase::BlockBackground:
        if (!m_vBar->isOverlayScrollbar())
            paintScrollbar(paintInfo, paintOffset);
        break;
    case PaintPhase::ChildBlockBackground:
    case PaintPhase::ChildBlockBackgrounds: {
        paintItem(paintInfo, paintOffset, [this](PaintInfo& paintInfo, const LayoutPoint& paintOffset, int listItemIndex) {
            paintItemBackground(paintInfo, paintOffset, listItemIndex);
        });
        break;
    }
    default:
        break;
    }
}

void RenderListBox::addFocusRingRects(Vector<LayoutRect>& rects, const LayoutPoint& additionalOffset, const RenderLayerModelObject* paintContainer)
{
    if (!selectElement().allowsNonContiguousSelection())
        return RenderBlockFlow::addFocusRingRects(rects, additionalOffset, paintContainer);

    // Focus the last selected item.
    int selectedItem = selectElement().activeSelectionEndListIndex();
    if (selectedItem >= 0) {
        rects.append(snappedIntRect(itemBoundingBoxRect(additionalOffset, selectedItem)));
        return;
    }

    // No selected items, find the first non-disabled item.
    int size = numItems();
    const Vector<HTMLElement*>& listItems = selectElement().listItems();
    for (int i = 0; i < size; ++i) {
        HTMLElement* element = listItems[i];
        if (is<HTMLOptionElement>(*element) && !element->isDisabledFormControl()) {
            selectElement().setActiveSelectionEndIndex(i);
            rects.append(itemBoundingBoxRect(additionalOffset, i));
            return;
        }
    }
}

void RenderListBox::paintScrollbar(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
    if (!m_vBar)
        return;

    LayoutUnit left = paintOffset.x() + (shouldPlaceVerticalScrollbarOnLeft() ? borderLeft() : width() - borderRight() - m_vBar->width());
    LayoutUnit top = paintOffset.y() + borderTop();
    LayoutUnit width = m_vBar->width();
    LayoutUnit height = this->height() - (borderTop() + borderBottom());
    IntRect scrollRect = snappedIntRect(left, top, width, height);
    m_vBar->setFrameRect(scrollRect);
    m_vBar->paint(paintInfo.context(), snappedIntRect(paintInfo.rect));
}

static LayoutSize itemOffsetForAlignment(TextRun textRun, const RenderStyle* itemStyle, FontCascade itemFont, LayoutRect itemBoudingBox)
{
    TextAlignMode actualAlignment = itemStyle->textAlign();
    // FIXME: Firefox doesn't respect TextAlignMode::Justify. Should we?
    // FIXME: Handle TextAlignMode::End here
    if (actualAlignment == TextAlignMode::Start || actualAlignment == TextAlignMode::Justify)
        actualAlignment = itemStyle->isLeftToRightDirection() ? TextAlignMode::Left : TextAlignMode::Right;

    LayoutSize offset = LayoutSize(0, itemFont.metricsOfPrimaryFont().ascent());
    if (actualAlignment == TextAlignMode::Right || actualAlignment == TextAlignMode::WebKitRight) {
        float textWidth = itemFont.width(textRun);
        offset.setWidth(itemBoudingBox.width() - textWidth - optionsSpacingHorizontal);
    } else if (actualAlignment == TextAlignMode::Center || actualAlignment == TextAlignMode::WebKitCenter) {
        float textWidth = itemFont.width(textRun);
        offset.setWidth((itemBoudingBox.width() - textWidth) / 2);
    } else
        offset.setWidth(optionsSpacingHorizontal);
    return offset;
}

void RenderListBox::paintItemForeground(PaintInfo& paintInfo, const LayoutPoint& paintOffset, int listIndex)
{
    const Vector<HTMLElement*>& listItems = selectElement().listItems();
    HTMLElement* listItemElement = listItems[listIndex];

    auto& itemStyle = *listItemElement->computedStyle();

    if (itemStyle.visibility() == Visibility::Hidden)
        return;

    String itemText;
    bool isOptionElement = is<HTMLOptionElement>(*listItemElement);
    if (isOptionElement)
        itemText = downcast<HTMLOptionElement>(*listItemElement).textIndentedToRespectGroupLabel();
    else if (is<HTMLOptGroupElement>(*listItemElement))
        itemText = downcast<HTMLOptGroupElement>(*listItemElement).groupLabelText();
    itemText = applyTextTransform(style(), itemText, ' ');

    if (itemText.isNull())
        return;

    Color textColor = itemStyle.visitedDependentColorWithColorFilter(CSSPropertyColor);
    if (isOptionElement && downcast<HTMLOptionElement>(*listItemElement).selected()) {
        if (frame().selection().isFocusedAndActive() && document().focusedElement() == &selectElement())
            textColor = theme().activeListBoxSelectionForegroundColor(styleColorOptions());
        // Honor the foreground color for disabled items
        else if (!listItemElement->isDisabledFormControl() && !selectElement().isDisabledFormControl())
            textColor = theme().inactiveListBoxSelectionForegroundColor(styleColorOptions());
    }

    paintInfo.context().setFillColor(textColor);

    TextRun textRun(itemText, 0, 0, ExpansionBehavior::allowRightOnly(), itemStyle.direction(), isOverride(itemStyle.unicodeBidi()), true);
    FontCascade itemFont = style().fontCascade();
    LayoutRect r = itemBoundingBoxRect(paintOffset, listIndex);
    r.move(itemOffsetForAlignment(textRun, &itemStyle, itemFont, r));

    if (is<HTMLOptGroupElement>(*listItemElement)) {
        auto description = itemFont.fontDescription();
        description.setWeight(description.bolderWeight());
        itemFont = FontCascade(WTFMove(description), itemFont.letterSpacing(), itemFont.wordSpacing());
        itemFont.update(&document().fontSelector());
    }

    // Draw the item text
    paintInfo.context().drawBidiText(itemFont, textRun, roundedIntPoint(r.location()));
}

void RenderListBox::paintItemBackground(PaintInfo& paintInfo, const LayoutPoint& paintOffset, int listIndex)
{
    const Vector<HTMLElement*>& listItems = selectElement().listItems();
    HTMLElement* listItemElement = listItems[listIndex];
    auto& itemStyle = *listItemElement->computedStyle();

    Color backColor;
    if (is<HTMLOptionElement>(*listItemElement) && downcast<HTMLOptionElement>(*listItemElement).selected()) {
        if (frame().selection().isFocusedAndActive() && document().focusedElement() == &selectElement())
            backColor = theme().activeListBoxSelectionBackgroundColor(styleColorOptions());
        else
            backColor = theme().inactiveListBoxSelectionBackgroundColor(styleColorOptions());
    } else
        backColor = itemStyle.visitedDependentColorWithColorFilter(CSSPropertyBackgroundColor);

    // Draw the background for this list box item
    if (itemStyle.visibility() == Visibility::Hidden)
        return;

    LayoutRect itemRect = itemBoundingBoxRect(paintOffset, listIndex);
    itemRect.intersect(controlClipRect(paintOffset));
    paintInfo.context().fillRect(snappedIntRect(itemRect), backColor);
}

bool RenderListBox::isPointInOverflowControl(HitTestResult& result, const LayoutPoint& locationInContainer, const LayoutPoint& accumulatedOffset)
{
    if (!m_vBar || !m_vBar->shouldParticipateInHitTesting())
        return false;

    LayoutUnit x = accumulatedOffset.x() + (shouldPlaceVerticalScrollbarOnLeft() ? borderLeft() : width() - borderRight() - m_vBar->width());
    LayoutUnit y = accumulatedOffset.y() + borderTop();
    LayoutUnit width = m_vBar->width();
    LayoutUnit height = this->height() - borderTop() - borderBottom();
    LayoutRect vertRect(x, y, width, height);

    if (!vertRect.contains(locationInContainer))
        return false;

    result.setScrollbar(m_vBar.get());
    return true;
}

int RenderListBox::listIndexAtOffset(const LayoutSize& offset)
{
    if (!numItems())
        return -1;

    if (offset.height() < borderTop() || offset.height() > height() - borderBottom())
        return -1;

    int scrollbarWidth = m_vBar ? m_vBar->width() : 0;
    if (shouldPlaceVerticalScrollbarOnLeft() && (offset.width() < borderLeft() + paddingLeft() + scrollbarWidth || offset.width() > width() - borderRight() - paddingRight()))
        return -1;
    if (!shouldPlaceVerticalScrollbarOnLeft() && (offset.width() < borderLeft() + paddingLeft() || offset.width() > width() - borderRight() - paddingRight() - scrollbarWidth))
        return -1;

    int newOffset = (offset.height() - borderTop() - paddingTop()) / itemHeight() + m_indexOffset;
    return newOffset < numItems() ? newOffset : -1;
}

void RenderListBox::panScroll(const IntPoint& panStartMousePosition)
{
    const int maxSpeed = 20;
    const int iconRadius = 7;
    const int speedReducer = 4;

    // FIXME: This doesn't work correctly with transforms.
    FloatPoint absOffset = localToAbsolute();

    IntPoint lastKnownMousePosition = frame().eventHandler().lastKnownMousePosition();
    // We need to check if the last known mouse position is out of the window. When the mouse is out of the window, the position is incoherent
    static IntPoint previousMousePosition;
    if (lastKnownMousePosition.y() < 0)
        lastKnownMousePosition = previousMousePosition;
    else
        previousMousePosition = lastKnownMousePosition;

    int yDelta = lastKnownMousePosition.y() - panStartMousePosition.y();

    // If the point is too far from the center we limit the speed
    yDelta = std::max<int>(std::min<int>(yDelta, maxSpeed), -maxSpeed);
    
    if (abs(yDelta) < iconRadius) // at the center we let the space for the icon
        return;

    if (yDelta > 0)
        //offsetY = view()->viewHeight();
        absOffset.move(0, listHeight());
    else if (yDelta < 0)
        yDelta--;

    // Let's attenuate the speed
    yDelta /= speedReducer;

    IntPoint scrollPoint(0, 0);
    scrollPoint.setY(absOffset.y() + yDelta);
    int newOffset = scrollToward(scrollPoint);
    if (newOffset < 0) 
        return;

    m_inAutoscroll = true;
    selectElement().updateListBoxSelection(!selectElement().multiple());
    m_inAutoscroll = false;
}

int RenderListBox::scrollToward(const IntPoint& destination)
{
    // FIXME: This doesn't work correctly with transforms.
    FloatPoint absPos = localToAbsolute();
    IntSize positionOffset = roundedIntSize(destination - absPos);

    int rows = numVisibleItems();
    int offset = m_indexOffset;
    
    if (positionOffset.height() < borderTop() + paddingTop() && scrollToRevealElementAtListIndex(offset - 1))
        return offset - 1;
    
    if (positionOffset.height() > height() - paddingBottom() - borderBottom() && scrollToRevealElementAtListIndex(offset + rows))
        return offset + rows - 1;
    
    return listIndexAtOffset(positionOffset);
}

void RenderListBox::autoscroll(const IntPoint&)
{
    IntPoint pos = frame().view()->windowToContents(frame().eventHandler().lastKnownMousePosition());

    int endIndex = scrollToward(pos);
    if (selectElement().isDisabledFormControl())
        return;

    if (endIndex >= 0) {
        m_inAutoscroll = true;

        if (!selectElement().multiple())
            selectElement().setActiveSelectionAnchorIndex(endIndex);

        selectElement().setActiveSelectionEndIndex(endIndex);
        selectElement().updateListBoxSelection(!selectElement().multiple());
        m_inAutoscroll = false;
    }
}

void RenderListBox::stopAutoscroll()
{
    if (selectElement().isDisabledFormControl())
        return;

    selectElement().listBoxOnChange();
}

bool RenderListBox::scrollToRevealElementAtListIndex(int index)
{
    if (index < 0 || index >= numItems() || listIndexIsVisible(index))
        return false;

    int newOffset;
    if (index < m_indexOffset)
        newOffset = index;
    else
        newOffset = index - numVisibleItems() + 1;

    scrollToOffsetWithoutAnimation(ScrollbarOrientation::Vertical, newOffset);

    return true;
}

bool RenderListBox::listIndexIsVisible(int index)
{
    int firstIndex = m_indexOfFirstVisibleItemInsidePaddingTopArea.value_or(m_indexOffset);
    int endIndex = m_indexOfFirstVisibleItemInsidePaddingBottomArea
        ? m_indexOfFirstVisibleItemInsidePaddingBottomArea.value() + numberOfVisibleItemsInPaddingBottom()
        : m_indexOffset + numVisibleItems();

    return index >= firstIndex && index < endIndex;
}

bool RenderListBox::scroll(ScrollDirection direction, ScrollGranularity granularity, unsigned stepCount, Element**, RenderBox*, const IntPoint&)
{
    return ScrollableArea::scroll(direction, granularity, stepCount);
}

bool RenderListBox::logicalScroll(ScrollLogicalDirection direction, ScrollGranularity granularity, unsigned stepCount, Element**)
{
    return ScrollableArea::scroll(logicalToPhysical(direction, style().isHorizontalWritingMode(), style().isFlippedBlocksWritingMode()), granularity, stepCount);
}

void RenderListBox::valueChanged(unsigned listIndex)
{
    selectElement().setSelectedIndex(selectElement().listToOptionIndex(listIndex));
    selectElement().dispatchFormControlChangeEvent();
}

ScrollPosition RenderListBox::scrollPosition() const
{
    return { 0, m_indexOffset };
}

ScrollPosition RenderListBox::minimumScrollPosition() const
{
    return { 0, 0 };
}

ScrollPosition RenderListBox::maximumScrollPosition() const
{
    return { 0, numItems() - numVisibleItems() };
}

void RenderListBox::setScrollOffset(const ScrollOffset& offset)
{
    scrollTo(offset.y());
}

int RenderListBox::maximumNumberOfItemsThatFitInPaddingBottomArea() const
{
    return paddingBottom() / itemHeight();
}

int RenderListBox::numberOfVisibleItemsInPaddingTop() const
{
    if (!m_indexOfFirstVisibleItemInsidePaddingTopArea)
        return 0;

    return m_indexOffset - m_indexOfFirstVisibleItemInsidePaddingTopArea.value();
}

int RenderListBox::numberOfVisibleItemsInPaddingBottom() const
{
    if (!m_indexOfFirstVisibleItemInsidePaddingBottomArea)
        return 0;

    return std::min(maximumNumberOfItemsThatFitInPaddingBottomArea(), numItems() - m_indexOffset - numVisibleItems());
}

void RenderListBox::computeFirstIndexesVisibleInPaddingTopBottomAreas()
{
    m_indexOfFirstVisibleItemInsidePaddingTopArea = std::nullopt;
    m_indexOfFirstVisibleItemInsidePaddingBottomArea = std::nullopt;

    int maximumNumberOfItemsThatFitInPaddingTopArea = paddingTop() / itemHeight();
    if (maximumNumberOfItemsThatFitInPaddingTopArea) {
        if (m_indexOffset)
            m_indexOfFirstVisibleItemInsidePaddingTopArea = std::max(0, m_indexOffset - maximumNumberOfItemsThatFitInPaddingTopArea);
    }

    if (maximumNumberOfItemsThatFitInPaddingBottomArea()) {
        if (numItems() > (m_indexOffset + numVisibleItems()))
            m_indexOfFirstVisibleItemInsidePaddingBottomArea = m_indexOffset + numVisibleItems();
    }
}

void RenderListBox::scrollTo(int newOffset)
{
    if (newOffset == m_indexOffset)
        return;

    m_indexOffset = newOffset;

    computeFirstIndexesVisibleInPaddingTopBottomAreas();

    repaint();
    document().addPendingScrollEventTarget(selectElement());
}

LayoutUnit RenderListBox::itemHeight() const
{
    return style().metricsOfPrimaryFont().height() + rowSpacing;
}

int RenderListBox::verticalScrollbarWidth() const
{
    return m_vBar ? m_vBar->occupiedWidth() : 0;
}

// FIXME: We ignore padding in the vertical direction as far as these values are concerned, since that's
// how the control currently paints.
int RenderListBox::scrollWidth() const
{
    // There is no horizontal scrolling allowed.
    return roundToInt(clientWidth());
}

int RenderListBox::scrollHeight() const
{
    return roundToInt(std::max(clientHeight(), listHeight()));
}

int RenderListBox::scrollLeft() const
{
    return 0;
}

void RenderListBox::setScrollLeft(int, const ScrollPositionChangeOptions&)
{
}

int RenderListBox::scrollTop() const
{
    return m_indexOffset * itemHeight();
}

static void setupWheelEventTestMonitor(RenderListBox& renderer)
{
    if (!renderer.page().isMonitoringWheelEvents())
        return;

    renderer.scrollAnimator().setWheelEventTestMonitor(renderer.page().wheelEventTestMonitor());
}

void RenderListBox::setScrollTop(int newTop, const ScrollPositionChangeOptions&)
{
    // Determine an index and scroll to it.    
    int index = newTop / itemHeight();
    if (index < 0 || index >= numItems() || index == m_indexOffset)
        return;

    setupWheelEventTestMonitor(*this);
    scrollToOffsetWithoutAnimation(ScrollbarOrientation::Vertical, index);
}

bool RenderListBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction)
{
    if (!RenderBlockFlow::nodeAtPoint(request, result, locationInContainer, accumulatedOffset, hitTestAction))
        return false;
    const Vector<HTMLElement*>& listItems = selectElement().listItems();
    int size = numItems();
    LayoutPoint adjustedLocation = accumulatedOffset + location();

    for (int i = 0; i < size; ++i) {
        if (!itemBoundingBoxRect(adjustedLocation, i).contains(locationInContainer.point()))
            continue;
        if (Element* node = listItems[i]) {
            result.setInnerNode(node);
            if (!result.innerNonSharedNode())
                result.setInnerNonSharedNode(node);
            result.setLocalPoint(locationInContainer.point() - toLayoutSize(adjustedLocation));
            break;
        }
    }

    return true;
}

LayoutRect RenderListBox::controlClipRect(const LayoutPoint& additionalOffset) const
{
    // Clip against the padding box, to give <option>s and overlay scrollbar some extra space
    // to get painted.
    LayoutRect clipRect = paddingBoxRect();
    clipRect.moveBy(additionalOffset);
    return clipRect;
}

bool RenderListBox::isActive() const
{
    return page().focusController().isActive();
}

void RenderListBox::invalidateScrollbarRect(Scrollbar& scrollbar, const IntRect& rect)
{
    IntRect scrollRect = rect;
    scrollRect.move(shouldPlaceVerticalScrollbarOnLeft() ? borderLeft() : width() - borderRight() - scrollbar.width(), borderTop());
    repaintRectangle(scrollRect);
}

IntRect RenderListBox::convertFromScrollbarToContainingView(const Scrollbar& scrollbar, const IntRect& scrollbarRect) const
{
    IntRect rect = scrollbarRect;
    int scrollbarLeft = shouldPlaceVerticalScrollbarOnLeft() ? borderLeft() : width() - borderRight() - scrollbar.width();
    int scrollbarTop = borderTop();
    rect.move(scrollbarLeft, scrollbarTop);
    return view().frameView().convertFromRendererToContainingView(this, rect);
}

IntRect RenderListBox::convertFromContainingViewToScrollbar(const Scrollbar& scrollbar, const IntRect& parentRect) const
{
    IntRect rect = view().frameView().convertFromContainingViewToRenderer(this, parentRect);
    int scrollbarLeft = shouldPlaceVerticalScrollbarOnLeft() ? borderLeft() : width() - borderRight() - scrollbar.width();
    int scrollbarTop = borderTop();
    rect.move(-scrollbarLeft, -scrollbarTop);
    return rect;
}

IntPoint RenderListBox::convertFromScrollbarToContainingView(const Scrollbar& scrollbar, const IntPoint& scrollbarPoint) const
{
    IntPoint point = scrollbarPoint;
    int scrollbarLeft = shouldPlaceVerticalScrollbarOnLeft() ? borderLeft() : width() - borderRight() - scrollbar.width();
    int scrollbarTop = borderTop();
    point.move(scrollbarLeft, scrollbarTop);
    return view().frameView().convertFromRendererToContainingView(this, point);
}

IntPoint RenderListBox::convertFromContainingViewToScrollbar(const Scrollbar& scrollbar, const IntPoint& parentPoint) const
{
    IntPoint point = view().frameView().convertFromContainingViewToRenderer(this, parentPoint);
    int scrollbarLeft = shouldPlaceVerticalScrollbarOnLeft() ? borderLeft() : width() - borderRight() - scrollbar.width();
    int scrollbarTop = borderTop();
    point.move(-scrollbarLeft, -scrollbarTop);
    return point;
}

IntSize RenderListBox::contentsSize() const
{
    return IntSize(scrollWidth(), scrollHeight());
}

IntPoint RenderListBox::lastKnownMousePositionInView() const
{
    return view().frameView().lastKnownMousePositionInView();
}

bool RenderListBox::isHandlingWheelEvent() const
{
    return view().frameView().isHandlingWheelEvent();
}

bool RenderListBox::shouldSuspendScrollAnimations() const
{
    return view().frameView().shouldSuspendScrollAnimations();
}

bool RenderListBox::forceUpdateScrollbarsOnMainThreadForPerformanceTesting() const
{
    return settings().scrollingPerformanceTestingEnabled();
}

ScrollableArea* RenderListBox::enclosingScrollableArea() const
{
    auto* layer = enclosingLayer();
    if (!layer)
        return nullptr;

    auto* enclosingScrollableLayer = layer->enclosingScrollableLayer(IncludeSelfOrNot::ExcludeSelf, CrossFrameBoundaries::No);
    if (!enclosingScrollableLayer)
        return nullptr;

    return enclosingScrollableLayer->scrollableArea();
}

bool RenderListBox::isScrollableOrRubberbandable()
{
    return m_vBar;
}

bool RenderListBox::hasScrollableOrRubberbandableAncestor()
{
    if (auto* scrollableArea = enclosingLayer() ? enclosingLayer()->scrollableArea() : nullptr)
        return scrollableArea->hasScrollableOrRubberbandableAncestor();
    return false;
}

IntRect RenderListBox::scrollableAreaBoundingBox(bool*) const
{
    return absoluteBoundingBoxRect();
}

bool RenderListBox::mockScrollbarsControllerEnabled() const
{
    return settings().mockScrollbarsControllerEnabled();
}

void RenderListBox::logMockScrollbarsControllerMessage(const String& message) const
{
    document().addConsoleMessage(MessageSource::Other, MessageLevel::Debug, "RenderListBox: " + message);
}

String RenderListBox::debugDescription() const
{
    return RenderObject::debugDescription();
}

void RenderListBox::didStartScrollAnimation()
{
    page().scheduleRenderingUpdate({ RenderingUpdateStep::Scroll });
}

Ref<Scrollbar> RenderListBox::createScrollbar()
{
    RefPtr<Scrollbar> widget;
    bool hasCustomScrollbarStyle = style().hasPseudoStyle(PseudoId::Scrollbar);
    if (hasCustomScrollbarStyle)
        widget = RenderScrollbar::createCustomScrollbar(*this, ScrollbarOrientation::Vertical, &selectElement());
    else {
        widget = Scrollbar::createNativeScrollbar(*this, ScrollbarOrientation::Vertical, theme().scrollbarControlSizeForPart(ListboxPart));
        didAddScrollbar(widget.get(), ScrollbarOrientation::Vertical);
        if (page().isMonitoringWheelEvents())
            scrollAnimator().setWheelEventTestMonitor(page().wheelEventTestMonitor());
    }
    view().frameView().addChild(*widget);
    return widget.releaseNonNull();
}

void RenderListBox::destroyScrollbar()
{
    if (!m_vBar)
        return;

    if (!m_vBar->isCustomScrollbar())
        ScrollableArea::willRemoveScrollbar(m_vBar.get(), ScrollbarOrientation::Vertical);
    m_vBar->removeFromParent();
    m_vBar = nullptr;
}

void RenderListBox::setHasVerticalScrollbar(bool hasScrollbar)
{
    if (hasScrollbar == (m_vBar != nullptr))
        return;

    if (hasScrollbar)
        m_vBar = createScrollbar();
    else
        destroyScrollbar();

    if (m_vBar)
        m_vBar->styleChanged();
}

bool RenderListBox::scrolledToTop() const
{
    if (Scrollbar* vbar = verticalScrollbar())
    return vbar->value() <= 0;

    return true;
}

bool RenderListBox::scrolledToBottom() const
{
    Scrollbar* vbar = verticalScrollbar();
    if (!vbar)
        return true;

    return vbar->value() >= vbar->maximum();
}

bool RenderListBox::scrolledToLeft() const
{
    // We do not scroll horizontally in a select element, so always report
    // that we are at the full extent of the scroll.
    return true;
}

bool RenderListBox::scrolledToRight() const
{
    // We do not scroll horizontally in a select element, so always report
    // that we are at the full extent of the scroll.
    return true;
}
    
} // namespace WebCore
