/*
 * Copyright (C) 2010 Google Inc. All rights reserved.
 * Copyright (C) 2011 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 "RangeInputType.h"

#include "AXObjectCache.h"
#include "ElementChildIterator.h"
#include "EventNames.h"
#include "HTMLInputElement.h"
#include "HTMLParserIdioms.h"
#include "InputTypeNames.h"
#include "KeyboardEvent.h"
#include "MouseEvent.h"
#include "PlatformMouseEvent.h"
#include "RenderSlider.h"
#include "ScopedEventQueue.h"
#include "ShadowRoot.h"
#include "SliderThumbElement.h"
#include <limits>
#include <wtf/MathExtras.h>
#include <wtf/NeverDestroyed.h>

#if ENABLE(TOUCH_EVENTS)
#include "Touch.h"
#include "TouchEvent.h"
#include "TouchList.h"
#endif

#if ENABLE(DATALIST_ELEMENT)
#include "HTMLDataListElement.h"
#include "HTMLOptionElement.h"
#endif

namespace WebCore {

using namespace HTMLNames;

static const int rangeDefaultMinimum = 0;
static const int rangeDefaultMaximum = 100;
static const int rangeDefaultStep = 1;
static const int rangeDefaultStepBase = 0;
static const int rangeStepScaleFactor = 1;

static Decimal ensureMaximum(const Decimal& proposedValue, const Decimal& minimum, const Decimal& fallbackValue)
{
    return proposedValue >= minimum ? proposedValue : std::max(minimum, fallbackValue);
}

RangeInputType::RangeInputType(HTMLInputElement& element)
    : InputType(element)
{
}

bool RangeInputType::isRangeControl() const
{
    return true;
}

const AtomicString& RangeInputType::formControlType() const
{
    return InputTypeNames::range();
}

double RangeInputType::valueAsDouble() const
{
    return parseToDoubleForNumberType(element().value());
}

ExceptionOr<void> RangeInputType::setValueAsDecimal(const Decimal& newValue, TextFieldEventBehavior eventBehavior) const
{
    element().setValue(serialize(newValue), eventBehavior);
    return { };
}

bool RangeInputType::typeMismatchFor(const String& value) const
{
    return !value.isEmpty() && !std::isfinite(parseToDoubleForNumberType(value));
}

bool RangeInputType::supportsRequired() const
{
    return false;
}

StepRange RangeInputType::createStepRange(AnyStepHandling anyStepHandling) const
{
    static NeverDestroyed<const StepRange::StepDescription> stepDescription(rangeDefaultStep, rangeDefaultStepBase, rangeStepScaleFactor);

    const Decimal minimum = parseToNumber(element().attributeWithoutSynchronization(minAttr), rangeDefaultMinimum);
    const Decimal maximum = ensureMaximum(parseToNumber(element().attributeWithoutSynchronization(maxAttr), rangeDefaultMaximum), minimum, rangeDefaultMaximum);

    const AtomicString& precisionValue = element().attributeWithoutSynchronization(precisionAttr);
    if (!precisionValue.isNull()) {
        const Decimal step = equalLettersIgnoringASCIICase(precisionValue, "float") ? Decimal::nan() : 1;
        return StepRange(minimum, RangeLimitations::Valid, minimum, maximum, step, stepDescription);
    }

    const Decimal step = StepRange::parseStep(anyStepHandling, stepDescription, element().attributeWithoutSynchronization(stepAttr));
    return StepRange(minimum, RangeLimitations::Valid, minimum, maximum, step, stepDescription);
}

bool RangeInputType::isSteppable() const
{
    return true;
}

#if !PLATFORM(IOS)

void RangeInputType::handleMouseDownEvent(MouseEvent& event)
{
    if (element().isDisabledFormControl())
        return;

    if (event.button() != LeftButton || !is<Node>(event.target()))
        return;
    ASSERT(element().shadowRoot());
    auto& targetNode = downcast<Node>(*event.target());
    if (&targetNode != &element() && !targetNode.isDescendantOf(element().userAgentShadowRoot().get()))
        return;
    auto& thumb = typedSliderThumbElement();
    if (&targetNode == &thumb)
        return;
    thumb.dragFrom(event.absoluteLocation());
}

#endif

#if ENABLE(TOUCH_EVENTS)
void RangeInputType::handleTouchEvent(TouchEvent& event)
{
#if PLATFORM(IOS)
    typedSliderThumbElement().handleTouchEvent(event);
#elif ENABLE(TOUCH_SLIDER)
    if (element().isDisabledFormControl())
        return;

    if (event.type() == eventNames().touchendEvent) {
        event.setDefaultHandled();
        return;
    }

    RefPtr<TouchList> touches = event.targetTouches();
    if (touches->length() == 1) {
        typedSliderThumbElement().setPositionFromPoint(touches->item(0)->absoluteLocation());
        event.setDefaultHandled();
    }
#else
    UNUSED_PARAM(event);
#endif
}

#if ENABLE(TOUCH_SLIDER)
bool RangeInputType::hasTouchEventHandler() const
{
    return true;
}
#endif
#endif // ENABLE(TOUCH_EVENTS)

void RangeInputType::disabledAttributeChanged()
{
    typedSliderThumbElement().disabledAttributeChanged();
}

void RangeInputType::handleKeydownEvent(KeyboardEvent& event)
{
    if (element().isDisabledFormControl())
        return;

    const String& key = event.keyIdentifier();

    const Decimal current = parseToNumberOrNaN(element().value());
    ASSERT(current.isFinite());

    StepRange stepRange(createStepRange(RejectAny));


    // FIXME: We can't use stepUp() for the step value "any". So, we increase
    // or decrease the value by 1/100 of the value range. Is it reasonable?
    const Decimal step = equalLettersIgnoringASCIICase(element().attributeWithoutSynchronization(stepAttr), "any") ? (stepRange.maximum() - stepRange.minimum()) / 100 : stepRange.step();
    const Decimal bigStep = std::max((stepRange.maximum() - stepRange.minimum()) / 10, step);

    bool isVertical = false;
    if (element().renderer()) {
        ControlPart part = element().renderer()->style().appearance();
        isVertical = part == SliderVerticalPart || part == MediaVolumeSliderPart;
    }

    Decimal newValue;
    if (key == "Up")
        newValue = current + step;
    else if (key == "Down")
        newValue = current - step;
    else if (key == "Left")
        newValue = isVertical ? current + step : current - step;
    else if (key == "Right")
        newValue = isVertical ? current - step : current + step;
    else if (key == "PageUp")
        newValue = current + bigStep;
    else if (key == "PageDown")
        newValue = current - bigStep;
    else if (key == "Home")
        newValue = isVertical ? stepRange.maximum() : stepRange.minimum();
    else if (key == "End")
        newValue = isVertical ? stepRange.minimum() : stepRange.maximum();
    else
        return; // Did not match any key binding.

    newValue = stepRange.clampValue(newValue);

    if (newValue != current) {
        EventQueueScope scope;
        setValueAsDecimal(newValue, DispatchInputAndChangeEvent);

        if (AXObjectCache* cache = element().document().existingAXObjectCache())
            cache->postNotification(&element(), AXObjectCache::AXValueChanged);
    }

    event.setDefaultHandled();
}

void RangeInputType::createShadowSubtree()
{
    ASSERT(element().userAgentShadowRoot());

    Document& document = element().document();
    auto track = HTMLDivElement::create(document);
    track->setPseudo(AtomicString("-webkit-slider-runnable-track", AtomicString::ConstructFromLiteral));
    track->appendChild(SliderThumbElement::create(document));
    auto container = SliderContainerElement::create(document);
    container->appendChild(track);
    element().userAgentShadowRoot()->appendChild(container);
}

HTMLElement* RangeInputType::sliderTrackElement() const
{
    ASSERT(element().userAgentShadowRoot());
    ASSERT(element().userAgentShadowRoot()->firstChild()); // container
    ASSERT(element().userAgentShadowRoot()->firstChild()->isHTMLElement());
    ASSERT(element().userAgentShadowRoot()->firstChild()->firstChild()); // track

    RefPtr<ShadowRoot> root = element().userAgentShadowRoot();
    if (!root)
        return nullptr;
    
    auto* container = childrenOfType<SliderContainerElement>(*root).first();
    if (!container)
        return nullptr;

    return childrenOfType<HTMLElement>(*container).first();
}

SliderThumbElement& RangeInputType::typedSliderThumbElement() const
{
    ASSERT(sliderTrackElement()->firstChild()); // thumb
    ASSERT(sliderTrackElement()->firstChild()->isHTMLElement());

    return static_cast<SliderThumbElement&>(*sliderTrackElement()->firstChild());
}

HTMLElement* RangeInputType::sliderThumbElement() const
{
    return &typedSliderThumbElement();
}

RenderPtr<RenderElement> RangeInputType::createInputRenderer(RenderStyle&& style)
{
    return createRenderer<RenderSlider>(element(), WTFMove(style));
}

Decimal RangeInputType::parseToNumber(const String& src, const Decimal& defaultValue) const
{
    return parseToDecimalForNumberType(src, defaultValue);
}

String RangeInputType::serialize(const Decimal& value) const
{
    if (!value.isFinite())
        return String();
    return serializeForNumberType(value);
}

// FIXME: Could share this with BaseClickableWithKeyInputType and BaseCheckableInputType if we had a common base class.
void RangeInputType::accessKeyAction(bool sendMouseEvents)
{
    InputType::accessKeyAction(sendMouseEvents);

    element().dispatchSimulatedClick(0, sendMouseEvents ? SendMouseUpDownEvents : SendNoEvents);
}

void RangeInputType::minOrMaxAttributeChanged()
{
    InputType::minOrMaxAttributeChanged();

    // Sanitize the value.
    if (element().hasDirtyValue())
        element().setValue(element().value());

    typedSliderThumbElement().setPositionFromValue();
}

void RangeInputType::setValue(const String& value, bool valueChanged, TextFieldEventBehavior eventBehavior)
{
    InputType::setValue(value, valueChanged, eventBehavior);

    if (!valueChanged)
        return;

    if (eventBehavior == DispatchNoEvent)
        element().setTextAsOfLastFormControlChangeEvent(value);

    typedSliderThumbElement().setPositionFromValue();
}

String RangeInputType::fallbackValue() const
{
    return serializeForNumberType(createStepRange(RejectAny).defaultValue());
}

String RangeInputType::sanitizeValue(const String& proposedValue) const
{
    StepRange stepRange(createStepRange(RejectAny));
    const Decimal proposedNumericValue = parseToNumber(proposedValue, stepRange.defaultValue());
    return serializeForNumberType(stepRange.clampValue(proposedNumericValue));
}

bool RangeInputType::shouldRespectListAttribute()
{
    return InputType::themeSupportsDataListUI(this);
}

#if ENABLE(DATALIST_ELEMENT)
void RangeInputType::listAttributeTargetChanged()
{
    m_tickMarkValuesDirty = true;
    RefPtr<HTMLElement> sliderTrackElement = this->sliderTrackElement();
    if (sliderTrackElement->renderer())
        sliderTrackElement->renderer()->setNeedsLayout();
}

void RangeInputType::updateTickMarkValues()
{
    if (!m_tickMarkValuesDirty)
        return;
    m_tickMarkValues.clear();
    m_tickMarkValuesDirty = false;
    auto dataList = element().dataList();
    if (!dataList)
        return;
    Ref<HTMLCollection> options = dataList->options();
    m_tickMarkValues.reserveCapacity(options->length());
    for (unsigned i = 0; i < options->length(); ++i) {
        RefPtr<Node> node = options->item(i);
        HTMLOptionElement& optionElement = downcast<HTMLOptionElement>(*node);
        String optionValue = optionElement.value();
        if (!element().isValidValue(optionValue))
            continue;
        m_tickMarkValues.append(parseToNumber(optionValue, Decimal::nan()));
    }
    m_tickMarkValues.shrinkToFit();
    std::sort(m_tickMarkValues.begin(), m_tickMarkValues.end());
}

std::optional<Decimal> RangeInputType::findClosestTickMarkValue(const Decimal& value)
{
    updateTickMarkValues();
    if (!m_tickMarkValues.size())
        return std::nullopt;

    size_t left = 0;
    size_t right = m_tickMarkValues.size();
    size_t middle;
    while (true) {
        ASSERT(left <= right);
        middle = left + (right - left) / 2;
        if (!middle)
            break;
        if (middle == m_tickMarkValues.size() - 1 && m_tickMarkValues[middle] < value) {
            middle++;
            break;
        }
        if (m_tickMarkValues[middle - 1] <= value && m_tickMarkValues[middle] >= value)
            break;

        if (m_tickMarkValues[middle] < value)
            left = middle;
        else
            right = middle;
    }

    std::optional<Decimal> closestLeft = middle ? std::make_optional(m_tickMarkValues[middle - 1]) : std::nullopt;
    std::optional<Decimal> closestRight = middle != m_tickMarkValues.size() ? std::make_optional(m_tickMarkValues[middle]) : std::nullopt;

    if (!closestLeft)
        return closestRight;
    if (!closestRight)
        return closestLeft;

    if (*closestRight - value < value - *closestLeft)
        return closestRight;

    return closestLeft;
}
#endif

} // namespace WebCore
