/*
 * Copyright (C) 2010 Google Inc. All rights reserved.
 * Copyright (C) 2011-2018 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 "RuntimeEnabledFeatures.h"
#include "ScopedEventQueue.h"
#include "ShadowRoot.h"
#include "SliderThumbElement.h"
#include <limits>
#include <wtf/MathExtras.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 const StepRange::StepDescription rangeStepDescription { rangeDefaultStep, rangeDefaultStepBase, rangeStepScaleFactor };

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 AtomString& RangeInputType::formControlType() const
{
    return InputTypeNames::range();
}

double RangeInputType::valueAsDouble() const
{
    ASSERT(element());
    return parseToDoubleForNumberType(element()->value());
}

ExceptionOr<void> RangeInputType::setValueAsDecimal(const Decimal& newValue, TextFieldEventBehavior eventBehavior) const
{
    ASSERT(element());
    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
{
    ASSERT(element());
    const Decimal minimum = parseToNumber(element()->attributeWithoutSynchronization(minAttr), rangeDefaultMinimum);
    const Decimal maximum = ensureMaximum(parseToNumber(element()->attributeWithoutSynchronization(maxAttr), rangeDefaultMaximum), minimum, rangeDefaultMaximum);

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

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

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

#if !PLATFORM(IOS_FAMILY)

void RangeInputType::handleMouseDownEvent(MouseEvent& event)
{
    ASSERT(element());
    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_FAMILY)
    typedSliderThumbElement().handleTouchEvent(event);
#elif ENABLE(TOUCH_SLIDER)
    ASSERT(element());
    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::disabledStateChanged()
{
    typedSliderThumbElement().hostDisabledStateChanged();
}

auto RangeInputType::handleKeydownEvent(KeyboardEvent& event) -> ShouldCallBaseEventHandler
{
    ASSERT(element());
    if (element()->isDisabledFormControl())
        return ShouldCallBaseEventHandler::Yes;

    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 (auto* renderer = element()->renderer()) {
        ControlPart part = 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 ShouldCallBaseEventHandler::Yes; // 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();
    return ShouldCallBaseEventHandler::Yes;
}

void RangeInputType::createShadowSubtree()
{
    ASSERT(element());
    ASSERT(element()->userAgentShadowRoot());

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

HTMLElement* RangeInputType::sliderTrackElement() const
{
    ASSERT(element());
    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)
{
    ASSERT(element());
    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);

    if (auto* element = this->element())
        element->dispatchSimulatedClick(0, sendMouseEvents ? SendMouseUpDownEvents : SendNoEvents);
}

void RangeInputType::attributeChanged(const QualifiedName& name)
{
    // FIXME: Don't we need to do this work for precisionAttr too?
    if (name == maxAttr || name == minAttr || name == valueAttr) {
        // Sanitize the value.
        if (auto* element = this->element()) {
            if (element->hasDirtyValue())
                element->setValue(element->value());
        }
        typedSliderThumbElement().setPositionFromValue();
    }
    InputType::attributeChanged(name);
}

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

    if (!valueChanged)
        return;

    if (eventBehavior == DispatchNoEvent) {
        ASSERT(element());
        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()
{
#if ENABLE(DATALIST_ELEMENT)
    return RuntimeEnabledFeatures::sharedFeatures().dataListElementEnabled();
#else
    return InputType::themeSupportsDataListUI(this);
#endif
}

#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;
    ASSERT(element());
    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());
}

Optional<Decimal> RangeInputType::findClosestTickMarkValue(const Decimal& value)
{
    updateTickMarkValues();
    if (!m_tickMarkValues.size())
        return WTF::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;
    }

    Optional<Decimal> closestLeft = middle ? makeOptional(m_tickMarkValues[middle - 1]) : WTF::nullopt;
    Optional<Decimal> closestRight = middle != m_tickMarkValues.size() ? makeOptional(m_tickMarkValues[middle]) : WTF::nullopt;

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

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

    return closestLeft;
}
#endif

} // namespace WebCore
