/*
 * 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;
}

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

#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
