/*
 * Copyright (C) 2006-2018 Apple Inc. All rights reserved.
 * Copyright (C) 2010 Google 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 "SliderThumbElement.h"

#include "CSSValueKeywords.h"
#include "Decimal.h"
#include "Event.h"
#include "EventHandler.h"
#include "EventNames.h"
#include "Frame.h"
#include "HTMLInputElement.h"
#include "HTMLParserIdioms.h"
#include "MouseEvent.h"
#include "RenderFlexibleBox.h"
#include "RenderSlider.h"
#include "RenderTheme.h"
#include "ShadowPseudoIds.h"
#include "ShadowRoot.h"
#include "StepRange.h"
#include "StyleResolver.h"
#include <wtf/IsoMallocInlines.h>

#if ENABLE(IOS_TOUCH_EVENTS)
#include "Document.h"
#include "Page.h"
#include "TouchEvent.h"
#endif

namespace WebCore {

using namespace HTMLNames;

WTF_MAKE_ISO_ALLOCATED_IMPL(SliderThumbElement);
WTF_MAKE_ISO_ALLOCATED_IMPL(SliderContainerElement);
WTF_MAKE_ISO_ALLOCATED_IMPL(RenderSliderThumb);

inline static Decimal sliderPosition(HTMLInputElement& element)
{
    const StepRange stepRange(element.createStepRange(AnyStepHandling::Reject));
    const Decimal oldValue = parseToDecimalForNumberType(element.value(), stepRange.defaultValue());
    return stepRange.proportionFromValue(stepRange.clampValue(oldValue));
}

inline static bool hasVerticalAppearance(HTMLInputElement& input)
{
    ASSERT(input.renderer());
    const RenderStyle& sliderStyle = input.renderer()->style();

#if ENABLE(VIDEO)
    if (sliderStyle.effectiveAppearance() == MediaVolumeSliderPart && input.renderer()->theme().usesVerticalVolumeSlider())
        return true;
#endif

    return sliderStyle.effectiveAppearance() == SliderVerticalPart;
}

// --------------------------------

RenderSliderThumb::RenderSliderThumb(SliderThumbElement& element, RenderStyle&& style)
    : RenderBlockFlow(element, WTFMove(style))
{
}

void RenderSliderThumb::updateAppearance(const RenderStyle* parentStyle)
{
    if (parentStyle->effectiveAppearance() == SliderVerticalPart)
        mutableStyle().setEffectiveAppearance(SliderThumbVerticalPart);
    else if (parentStyle->effectiveAppearance() == SliderHorizontalPart)
        mutableStyle().setEffectiveAppearance(SliderThumbHorizontalPart);
    else if (parentStyle->effectiveAppearance() == MediaSliderPart)
        mutableStyle().setEffectiveAppearance(MediaSliderThumbPart);
    else if (parentStyle->effectiveAppearance() == MediaVolumeSliderPart)
        mutableStyle().setEffectiveAppearance(MediaVolumeSliderThumbPart);
    else if (parentStyle->effectiveAppearance() == MediaFullScreenVolumeSliderPart)
        mutableStyle().setEffectiveAppearance(MediaFullScreenVolumeSliderThumbPart);
    if (style().hasEffectiveAppearance()) {
        ASSERT(element());
        theme().adjustSliderThumbSize(mutableStyle(), element());
    }
}

bool RenderSliderThumb::isSliderThumb() const
{
    return true;
}

// --------------------------------

// FIXME: Find a way to cascade appearance and adjust heights, and get rid of this class.
// http://webkit.org/b/62535
class RenderSliderContainer final : public RenderFlexibleBox {
    WTF_MAKE_ISO_ALLOCATED_INLINE(RenderSliderContainer);
public:
    RenderSliderContainer(SliderContainerElement& element, RenderStyle&& style)
        : RenderFlexibleBox(element, WTFMove(style))
    {
    }

public:
    RenderBox::LogicalExtentComputedValues computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop) const override;

private:
    void layout() override;
    bool isFlexibleBoxImpl() const override { return true; }
};

RenderBox::LogicalExtentComputedValues RenderSliderContainer::computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop) const
{
    ASSERT(element()->shadowHost());
    auto& input = downcast<HTMLInputElement>(*element()->shadowHost());
    bool isVertical = hasVerticalAppearance(input);

#if ENABLE(DATALIST_ELEMENT)
    if (input.renderer()->isSlider() && !isVertical && input.list()) {
        int offsetFromCenter = theme().sliderTickOffsetFromTrackCenter();
        LayoutUnit trackHeight;
        if (offsetFromCenter < 0)
            trackHeight = -2 * offsetFromCenter;
        else {
            int tickLength = theme().sliderTickSize().height();
            trackHeight = 2 * (offsetFromCenter + tickLength);
        }
        float zoomFactor = style().effectiveZoom();
        if (zoomFactor != 1.0)
            trackHeight *= zoomFactor;

        return RenderBox::computeLogicalHeight(trackHeight, logicalTop);
    }
#endif
    if (isVertical)
        logicalHeight = RenderSlider::defaultTrackLength;
    return RenderBox::computeLogicalHeight(logicalHeight, logicalTop);
}

void RenderSliderContainer::layout()
{
    ASSERT(element()->shadowHost());
    auto& input = downcast<HTMLInputElement>(*element()->shadowHost());
    bool isVertical = hasVerticalAppearance(input);
    mutableStyle().setFlexDirection(isVertical ? FlexDirection::Column : FlexDirection::Row);
    TextDirection oldTextDirection = style().direction();
    if (isVertical) {
        // FIXME: Work around rounding issues in RTL vertical sliders. We want them to
        // render identically to LTR vertical sliders. We can remove this work around when
        // subpixel rendering is enabled on all ports.
        mutableStyle().setDirection(TextDirection::LTR);
    }

    RenderBox* thumb = input.sliderThumbElement() ? input.sliderThumbElement()->renderBox() : nullptr;
    RenderBox* track = input.sliderTrackElement() ? input.sliderTrackElement()->renderBox() : nullptr;
    // Force a layout to reset the position of the thumb so the code below doesn't move the thumb to the wrong place.
    // FIXME: Make a custom Render class for the track and move the thumb positioning code there.
    if (track)
        track->setChildNeedsLayout(MarkOnlyThis);

    RenderFlexibleBox::layout();

    mutableStyle().setDirection(oldTextDirection);
    // These should always exist, unless someone mutates the shadow DOM (e.g., in the inspector).
    if (!thumb || !track)
        return;

    double percentageOffset = sliderPosition(input).toDouble();
    LayoutUnit availableExtent = isVertical ? track->contentHeight() : track->contentWidth();
    availableExtent -= isVertical ? thumb->height() : thumb->width();
    LayoutUnit offset { percentageOffset * availableExtent };
    LayoutPoint thumbLocation = thumb->location();
    if (isVertical)
        thumbLocation.setY(thumbLocation.y() + track->contentHeight() - thumb->height() - offset);
    else if (style().isLeftToRightDirection())
        thumbLocation.setX(thumbLocation.x() + offset);
    else
        thumbLocation.setX(thumbLocation.x() - offset);
    thumb->setLocation(thumbLocation);
    thumb->repaint();
}

// --------------------------------

SliderThumbElement::SliderThumbElement(Document& document)
    : HTMLDivElement(HTMLNames::divTag, document)
{
    setHasCustomStyleResolveCallbacks();
}

void SliderThumbElement::setPositionFromValue()
{
    // Since the code to calculate position is in the RenderSliderThumb layout
    // path, we don't actually update the value here. Instead, we poke at the
    // renderer directly to trigger layout.
    if (renderer())
        renderer()->setNeedsLayout();
}

RenderPtr<RenderElement> SliderThumbElement::createElementRenderer(RenderStyle&& style, const RenderTreePosition&)
{
    return createRenderer<RenderSliderThumb>(*this, WTFMove(style));
}

bool SliderThumbElement::isDisabledFormControl() const
{
    auto input = hostInput();
    return !input || input->isDisabledFormControl();
}

bool SliderThumbElement::matchesReadWritePseudoClass() const
{
    auto input = hostInput();
    return input && input->matchesReadWritePseudoClass();
}

RefPtr<Element> SliderThumbElement::focusDelegate()
{
    return hostInput();
}

void SliderThumbElement::dragFrom(const LayoutPoint& point)
{
    Ref<SliderThumbElement> protectedThis(*this);
    setPositionFromPoint(point);
    startDragging();
}

void SliderThumbElement::setPositionFromPoint(const LayoutPoint& absolutePoint)
{
    auto input = hostInput();
    if (!input)
        return;

    auto* inputRenderer = input->renderBox();
    if (!inputRenderer)
        return;

    auto* thumbRenderer = renderBox();
    if (!thumbRenderer)
        return;

    ASSERT(input->sliderTrackElement());
    auto* trackRenderer = input->sliderTrackElement()->renderBox();
    if (!trackRenderer)
        return;

    // Do all the tracking math relative to the input's renderer's box.

    bool isVertical = hasVerticalAppearance(*input);
    bool isLeftToRightDirection = thumbRenderer->style().isLeftToRightDirection();
    
    auto offset = inputRenderer->absoluteToLocal(absolutePoint, UseTransforms);
    auto trackBoundingBox = trackRenderer->localToContainerQuad(FloatRect { { }, trackRenderer->size() }, inputRenderer).enclosingBoundingBox();

    LayoutUnit trackLength;
    LayoutUnit position;
    if (isVertical) {
        trackLength = trackRenderer->contentHeight() - thumbRenderer->height();
        position = offset.y() - thumbRenderer->height() / 2 - trackBoundingBox.y() - thumbRenderer->marginBottom();
    } else {
        trackLength = trackRenderer->contentWidth() - thumbRenderer->width();
        position = offset.x() - thumbRenderer->width() / 2 - trackBoundingBox.x();
        position -= isLeftToRightDirection ? thumbRenderer->marginLeft() : thumbRenderer->marginRight();
    }

    position = std::max<LayoutUnit>(0, std::min(position, trackLength));
    auto ratio = Decimal::fromDouble(static_cast<double>(position) / trackLength);
    auto fraction = isVertical || !isLeftToRightDirection ? Decimal(1) - ratio : ratio;
    auto stepRange = input->createStepRange(AnyStepHandling::Reject);
    auto value = stepRange.clampValue(stepRange.valueFromProportion(fraction));

#if ENABLE(DATALIST_ELEMENT)
    const LayoutUnit snappingThreshold = renderer()->theme().sliderTickSnappingThreshold();
    if (snappingThreshold > 0) {
        if (std::optional<Decimal> closest = input->findClosestTickMarkValue(value)) {
            double closestFraction = stepRange.proportionFromValue(*closest).toDouble();
            double closestRatio = isVertical || !isLeftToRightDirection ? 1.0 - closestFraction : closestFraction;
            LayoutUnit closestPosition { trackLength * closestRatio };
            if ((closestPosition - position).abs() <= snappingThreshold)
                value = *closest;
        }
    }
#endif

    String valueString = serializeForNumberType(value);
    if (valueString == input->value())
        return;

    // FIXME: This is no longer being set from renderer. Consider updating the method name.
    input->setValueFromRenderer(valueString);
    if (renderer())
        renderer()->setNeedsLayout();
}

void SliderThumbElement::startDragging()
{
    if (RefPtr<Frame> frame = document().frame()) {
        frame->eventHandler().setCapturingMouseEventsElement(this);
        m_inDragMode = true;
    }
}

void SliderThumbElement::stopDragging()
{
    if (!m_inDragMode)
        return;

    if (RefPtr<Frame> frame = document().frame())
        frame->eventHandler().setCapturingMouseEventsElement(nullptr);
    m_inDragMode = false;
    if (renderer())
        renderer()->setNeedsLayout();
}

void SliderThumbElement::defaultEventHandler(Event& event)
{
    if (!is<MouseEvent>(event)) {
        HTMLDivElement::defaultEventHandler(event);
        return;
    }

    // FIXME: Should handle this readonly/disabled check in more general way.
    // Missing this kind of check is likely to occur elsewhere if adding it in each shadow element.
    auto input = hostInput();
    if (!input || input->isDisabledFormControl()) {
        HTMLDivElement::defaultEventHandler(event);
        return;
    }

    MouseEvent& mouseEvent = downcast<MouseEvent>(event);
    bool isLeftButton = mouseEvent.button() == LeftButton;
    const AtomString& eventType = mouseEvent.type();

    // We intentionally do not call event->setDefaultHandled() here because
    // MediaControlTimelineElement::defaultEventHandler() wants to handle these
    // mouse events.
    if (eventType == eventNames().mousedownEvent && isLeftButton) {
        startDragging();
        return;
    } else if (eventType == eventNames().mouseupEvent && isLeftButton) {
        input->dispatchFormControlChangeEvent();
        stopDragging();
        return;
    } else if (eventType == eventNames().mousemoveEvent) {
        if (m_inDragMode)
            setPositionFromPoint(mouseEvent.absoluteLocation());
        return;
    }

    HTMLDivElement::defaultEventHandler(mouseEvent);
}

bool SliderThumbElement::willRespondToMouseMoveEvents()
{
    const auto input = hostInput();
    if (input && !input->isDisabledFormControl() && m_inDragMode)
        return true;

    return HTMLDivElement::willRespondToMouseMoveEvents();
}

bool SliderThumbElement::willRespondToMouseClickEvents()
{
    const auto input = hostInput();
    if (input && !input->isDisabledFormControl())
        return true;

    return HTMLDivElement::willRespondToMouseClickEvents();
}


void SliderThumbElement::willDetachRenderers()
{
    if (m_inDragMode) {
        if (RefPtr<Frame> frame = document().frame())
            frame->eventHandler().setCapturingMouseEventsElement(nullptr);
    }
#if ENABLE(IOS_TOUCH_EVENTS)
    unregisterForTouchEvents();
#endif
}

#if ENABLE(IOS_TOUCH_EVENTS)

unsigned SliderThumbElement::exclusiveTouchIdentifier() const
{
    return m_exclusiveTouchIdentifier;
}

void SliderThumbElement::setExclusiveTouchIdentifier(unsigned identifier)
{
    ASSERT(m_exclusiveTouchIdentifier == NoIdentifier);
    m_exclusiveTouchIdentifier = identifier;
}

void SliderThumbElement::clearExclusiveTouchIdentifier()
{
    m_exclusiveTouchIdentifier = NoIdentifier;
}

static Touch* findTouchWithIdentifier(TouchList& list, unsigned identifier)
{
    unsigned length = list.length();
    for (unsigned i = 0; i < length; ++i) {
        RefPtr<Touch> touch = list.item(i);
        if (touch->identifier() == identifier)
            return touch.get();
    }
    return nullptr;
}

void SliderThumbElement::handleTouchStart(TouchEvent& touchEvent)
{
    RefPtr<TouchList> targetTouches = touchEvent.targetTouches();
    if (!targetTouches)
        return;

    if (targetTouches->length() != 1)
        return;

    RefPtr<Touch> touch = targetTouches->item(0);
    if (!renderer())
        return;
    IntRect boundingBox = renderer()->absoluteBoundingBoxRect();
    // Ignore the touch if it is not really inside the thumb.
    if (!boundingBox.contains(touch->pageX(), touch->pageY()))
        return;

    setExclusiveTouchIdentifier(touch->identifier());

    startDragging();
    touchEvent.setDefaultHandled();
}

void SliderThumbElement::handleTouchMove(TouchEvent& touchEvent)
{
    unsigned identifier = exclusiveTouchIdentifier();
    if (identifier == NoIdentifier)
        return;

    RefPtr<TouchList> targetTouches = touchEvent.targetTouches();
    if (!targetTouches)
        return;

    RefPtr<Touch> touch = findTouchWithIdentifier(*targetTouches, identifier);
    if (!touch)
        return;

    if (m_inDragMode)
        setPositionFromPoint(IntPoint(touch->pageX(), touch->pageY()));
    touchEvent.setDefaultHandled();
}

void SliderThumbElement::handleTouchEndAndCancel(TouchEvent& touchEvent)
{
    unsigned identifier = exclusiveTouchIdentifier();
    if (identifier == NoIdentifier)
        return;

    RefPtr<TouchList> targetTouches = touchEvent.targetTouches();
    if (!targetTouches)
        return;
    // If our exclusive touch still exists, it was not the touch
    // that ended, so we should not stop dragging.
    RefPtr<Touch> exclusiveTouch = findTouchWithIdentifier(*targetTouches, identifier);
    if (exclusiveTouch)
        return;

    clearExclusiveTouchIdentifier();

    auto input = hostInput();
    if (input)
        input->dispatchFormControlChangeEvent();
    stopDragging();
}

void SliderThumbElement::didAttachRenderers()
{
    if (shouldAcceptTouchEvents())
        registerForTouchEvents();
}

void SliderThumbElement::handleTouchEvent(TouchEvent& touchEvent)
{
    auto input = hostInput();
    ASSERT(input);
    if (input->isReadOnly() || input->isDisabledFormControl()) {
        clearExclusiveTouchIdentifier();
        stopDragging();
        touchEvent.setDefaultHandled();
        HTMLDivElement::defaultEventHandler(touchEvent);
        return;
    }

    const AtomString& eventType = touchEvent.type();
    if (eventType == eventNames().touchstartEvent) {
        handleTouchStart(touchEvent);
        return;
    }
    if (eventType == eventNames().touchendEvent || eventType == eventNames().touchcancelEvent) {
        handleTouchEndAndCancel(touchEvent);
        return;
    }
    if (eventType == eventNames().touchmoveEvent) {
        handleTouchMove(touchEvent);
        return;
    }

    HTMLDivElement::defaultEventHandler(touchEvent);
}

bool SliderThumbElement::shouldAcceptTouchEvents()
{
    return renderer() && !isDisabledFormControl();
}

void SliderThumbElement::registerForTouchEvents()
{
    if (m_isRegisteredAsTouchEventListener)
        return;

    ASSERT(shouldAcceptTouchEvents());

    document().addTouchEventHandler(*this);
    m_isRegisteredAsTouchEventListener = true;
}

void SliderThumbElement::unregisterForTouchEvents()
{
    if (!m_isRegisteredAsTouchEventListener)
        return;

    clearExclusiveTouchIdentifier();
    stopDragging();

    document().removeTouchEventHandler(*this);
    m_isRegisteredAsTouchEventListener = false;
}

#endif // ENABLE(IOS_TOUCH_EVENTS)

void SliderThumbElement::hostDisabledStateChanged()
{
    if (isDisabledFormControl())
        stopDragging();

#if ENABLE(IOS_TOUCH_EVENTS)
    if (shouldAcceptTouchEvents())
        registerForTouchEvents();
    else
        unregisterForTouchEvents();
#endif
}

RefPtr<HTMLInputElement> SliderThumbElement::hostInput() const
{
    // Only HTMLInputElement creates SliderThumbElement instances as its shadow nodes.
    // So, shadowHost() must be an HTMLInputElement.
    return downcast<HTMLInputElement>(shadowHost());
}

std::optional<Style::ElementStyle> SliderThumbElement::resolveCustomStyle(const RenderStyle&, const RenderStyle* hostStyle)
{
    // This doesn't actually compute style. This is just a hack to pick shadow pseudo id when host style is known.

    if (!hostStyle)
        return std::nullopt;

    switch (hostStyle->effectiveAppearance()) {
    case MediaSliderPart:
    case MediaSliderThumbPart:
    case MediaVolumeSliderPart:
    case MediaVolumeSliderThumbPart:
    case MediaFullScreenVolumeSliderPart:
    case MediaFullScreenVolumeSliderThumbPart:
        m_shadowPseudoId = ShadowPseudoIds::webkitMediaSliderThumb();
        break;
    default:
        m_shadowPseudoId = ShadowPseudoIds::webkitSliderThumb();
    }

    return std::nullopt;
}

const AtomString& SliderThumbElement::shadowPseudoId() const
{
    return m_shadowPseudoId;
}

Ref<Element> SliderThumbElement::cloneElementWithoutAttributesAndChildren(Document& targetDocument)
{
    return create(targetDocument);
}

// --------------------------------

inline SliderContainerElement::SliderContainerElement(Document& document)
    : HTMLDivElement(HTMLNames::divTag, document)
{
    setHasCustomStyleResolveCallbacks();
}

Ref<SliderContainerElement> SliderContainerElement::create(Document& document)
{
    return adoptRef(*new SliderContainerElement(document));
}

RenderPtr<RenderElement> SliderContainerElement::createElementRenderer(RenderStyle&& style, const RenderTreePosition&)
{
    return createRenderer<RenderSliderContainer>(*this, WTFMove(style));
}

std::optional<Style::ElementStyle> SliderContainerElement::resolveCustomStyle(const RenderStyle&, const RenderStyle* hostStyle)
{
    // This doesn't actually compute style. This is just a hack to pick shadow pseudo id when host style is known.

    if (!hostStyle)
        return std::nullopt;

    switch (hostStyle->effectiveAppearance()) {
    case MediaSliderPart:
    case MediaSliderThumbPart:
    case MediaVolumeSliderPart:
    case MediaVolumeSliderThumbPart:
    case MediaFullScreenVolumeSliderPart:
    case MediaFullScreenVolumeSliderThumbPart:
        m_shadowPseudoId = ShadowPseudoIds::webkitMediaSliderContainer();
        break;
    default:
        m_shadowPseudoId = ShadowPseudoIds::webkitSliderContainer();
    }

    return std::nullopt;
}

const AtomString& SliderContainerElement::shadowPseudoId() const
{
    return m_shadowPseudoId;
}

}
