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

#if ENABLE(DATE_AND_TIME_INPUT_TYPES)

#include "BaseClickableWithKeyInputType.h"
#include "Chrome.h"
#include "DateComponents.h"
#include "DateTimeChooserParameters.h"
#include "Decimal.h"
#include "FocusController.h"
#include "FrameView.h"
#include "HTMLDataListElement.h"
#include "HTMLDivElement.h"
#include "HTMLInputElement.h"
#include "HTMLNames.h"
#include "HTMLOptionElement.h"
#include "KeyboardEvent.h"
#include "Page.h"
#include "PlatformLocale.h"
#include "Settings.h"
#include "ShadowPseudoIds.h"
#include "ShadowRoot.h"
#include "StepRange.h"
#include "Text.h"
#include "UserGestureIndicator.h"
#include <limits>
#include <wtf/DateMath.h>
#include <wtf/MathExtras.h>
#include <wtf/text/StringView.h>

namespace WebCore {

using namespace HTMLNames;

static const int msecPerMinute = 60 * 1000;
static const int msecPerSecond = 1000;

void BaseDateAndTimeInputType::DateTimeFormatValidator::visitField(DateTimeFormat::FieldType fieldType, int)
{
    switch (fieldType) {
    case DateTimeFormat::FieldTypeYear:
        m_results.add(DateTimeFormatValidationResults::HasYear);
        break;

    case DateTimeFormat::FieldTypeMonth:
    case DateTimeFormat::FieldTypeMonthStandAlone:
        m_results.add(DateTimeFormatValidationResults::HasMonth);
        break;

    case DateTimeFormat::FieldTypeWeekOfYear:
        m_results.add(DateTimeFormatValidationResults::HasWeek);
        break;

    case DateTimeFormat::FieldTypeDayOfMonth:
        m_results.add(DateTimeFormatValidationResults::HasDay);
        break;

    case DateTimeFormat::FieldTypePeriod:
        m_results.add(DateTimeFormatValidationResults::HasMeridiem);
        break;

    case DateTimeFormat::FieldTypeHour11:
    case DateTimeFormat::FieldTypeHour12:
        m_results.add(DateTimeFormatValidationResults::HasHour);
        break;

    case DateTimeFormat::FieldTypeHour23:
    case DateTimeFormat::FieldTypeHour24:
        m_results.add(DateTimeFormatValidationResults::HasHour);
        m_results.add(DateTimeFormatValidationResults::HasMeridiem);
        break;

    case DateTimeFormat::FieldTypeMinute:
        m_results.add(DateTimeFormatValidationResults::HasMinute);
        break;

    case DateTimeFormat::FieldTypeSecond:
        m_results.add(DateTimeFormatValidationResults::HasSecond);
        break;

    default:
        break;
    }
}

bool BaseDateAndTimeInputType::DateTimeFormatValidator::validateFormat(const String& format, const BaseDateAndTimeInputType& inputType)
{
    if (!DateTimeFormat::parse(format, *this))
        return false;
    return inputType.isValidFormat(m_results);
}

BaseDateAndTimeInputType::~BaseDateAndTimeInputType()
{
    closeDateTimeChooser();
}

WallTime BaseDateAndTimeInputType::valueAsDate() const
{
    return WallTime::fromRawSeconds(Seconds::fromMilliseconds(valueAsDouble()).value());
}

ExceptionOr<void> BaseDateAndTimeInputType::setValueAsDate(WallTime value) const
{
    ASSERT(element());
    element()->setValue(serializeWithMilliseconds(value.secondsSinceEpoch().milliseconds()));
    return { };
}

double BaseDateAndTimeInputType::valueAsDouble() const
{
    ASSERT(element());
    const Decimal value = parseToNumber(element()->value(), Decimal::nan());
    return value.isFinite() ? value.toDouble() : DateComponents::invalidMilliseconds();
}

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

bool BaseDateAndTimeInputType::typeMismatchFor(const String& value) const
{
    return !value.isEmpty() && !parseToDateComponents(value);
}

bool BaseDateAndTimeInputType::typeMismatch() const
{
    ASSERT(element());
    return typeMismatchFor(element()->value());
}

Decimal BaseDateAndTimeInputType::defaultValueForStepUp() const
{
    double ms = WallTime::now().secondsSinceEpoch().milliseconds();
    int offset = calculateLocalTimeOffset(ms).offset / msPerMinute;
    return Decimal::fromDouble(ms + (offset * msPerMinute));
}

Decimal BaseDateAndTimeInputType::parseToNumber(const String& source, const Decimal& defaultValue) const
{
    auto date = parseToDateComponents(source);
    if (!date)
        return defaultValue;
    double msec = date->millisecondsSinceEpoch();
    ASSERT(std::isfinite(msec));
    return Decimal::fromDouble(msec);
}

String BaseDateAndTimeInputType::serialize(const Decimal& value) const
{
    if (!value.isFinite())
        return { };
    auto date = setMillisecondToDateComponents(value.toDouble());
    if (!date)
        return { };
    return serializeWithComponents(*date);
}

String BaseDateAndTimeInputType::serializeWithComponents(const DateComponents& date) const
{
    ASSERT(element());
    Decimal step;
    if (!element()->getAllowedValueStep(&step) || step.remainder(msecPerMinute).isZero())
        return date.toString();
    if (step.remainder(msecPerSecond).isZero())
        return date.toString(SecondFormat::Second);
    return date.toString(SecondFormat::Millisecond);
}

String BaseDateAndTimeInputType::serializeWithMilliseconds(double value) const
{
    return serialize(Decimal::fromDouble(value));
}

String BaseDateAndTimeInputType::localizeValue(const String& proposedValue) const
{
    auto date = parseToDateComponents(proposedValue);
    if (!date)
        return proposedValue;

    ASSERT(element());
    String localized = element()->locale().formatDateTime(*date);
    return localized.isEmpty() ? proposedValue : localized;
}

String BaseDateAndTimeInputType::visibleValue() const
{
    ASSERT(element());
    return localizeValue(element()->value());
}

String BaseDateAndTimeInputType::sanitizeValue(const String& proposedValue) const
{
    return typeMismatchFor(proposedValue) ? String() : proposedValue;
}

bool BaseDateAndTimeInputType::supportsReadOnly() const
{
    return true;
}

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

bool BaseDateAndTimeInputType::valueMissing(const String& value) const
{
    ASSERT(element());
    return !element()->isDisabledOrReadOnly() && element()->isRequired() && value.isEmpty();
}

bool BaseDateAndTimeInputType::isKeyboardFocusable(KeyboardEvent*) const
{
    ASSERT(element());
    return !element()->isReadOnly() && element()->isTextFormControlFocusable();
}

bool BaseDateAndTimeInputType::isMouseFocusable() const
{
    ASSERT(element());
    return element()->isTextFormControlFocusable();
}

bool BaseDateAndTimeInputType::shouldHaveSecondField(const DateComponents& date) const
{
    if (date.second())
        return true;

    auto stepRange = createStepRange(AnyStepHandling::Default);
    return !stepRange.minimum().remainder(msecPerMinute).isZero()
        || !stepRange.step().remainder(msecPerMinute).isZero();
}

bool BaseDateAndTimeInputType::shouldHaveMillisecondField(const DateComponents& date) const
{
    if (date.millisecond())
        return true;

    auto stepRange = createStepRange(AnyStepHandling::Default);
    return !stepRange.minimum().remainder(msecPerSecond).isZero()
        || !stepRange.step().remainder(msecPerSecond).isZero();
}

void BaseDateAndTimeInputType::setValue(const String& value, bool valueChanged, TextFieldEventBehavior eventBehavior, TextControlSetValueSelection selection)
{
    InputType::setValue(value, valueChanged, eventBehavior, selection);
    if (valueChanged)
        updateInnerTextValue();
}

void BaseDateAndTimeInputType::handleDOMActivateEvent(Event&)
{
    ASSERT(element());
    if (element()->isDisabledOrReadOnly() || !element()->renderer() || !UserGestureIndicator::processingUserGesture())
        return;

    if (m_dateTimeChooser)
        return;
    if (!element()->document().page())
        return;

    DateTimeChooserParameters parameters;
    if (!setupDateTimeChooserParameters(parameters))
        return;

    if (auto chrome = this->chrome()) {
        m_dateTimeChooser = chrome->createDateTimeChooser(*this);
        if (m_dateTimeChooser)
            m_dateTimeChooser->showChooser(parameters);
    }
}

void BaseDateAndTimeInputType::createShadowSubtree()
{
    ASSERT(needsShadowSubtree());
    ASSERT(element());

    auto& element = *this->element();
    auto& document = element.document();

    if (document.settings().dateTimeInputsEditableComponentsEnabled()) {
        m_dateTimeEditElement = DateTimeEditElement::create(document, *this);
        element.userAgentShadowRoot()->appendChild(ContainerNode::ChildChange::Source::Parser, *m_dateTimeEditElement);
    } else {
        auto valueContainer = HTMLDivElement::create(document);
        valueContainer->setPseudo(ShadowPseudoIds::webkitDateAndTimeValue());
        element.userAgentShadowRoot()->appendChild(ContainerNode::ChildChange::Source::Parser, valueContainer);
    }
    updateInnerTextValue();
}

void BaseDateAndTimeInputType::destroyShadowSubtree()
{
    InputType::destroyShadowSubtree();
    m_dateTimeEditElement = nullptr;
}

void BaseDateAndTimeInputType::updateInnerTextValue()
{
    ASSERT(element());

    createShadowSubtreeIfNeeded();

    if (!m_dateTimeEditElement) {
        auto node = element()->userAgentShadowRoot()->firstChild();
        if (!is<HTMLElement>(node))
            return;
        auto displayValue = visibleValue();
        if (displayValue.isEmpty()) {
            // Need to put something to keep text baseline.
            displayValue = " "_s;
        }
        downcast<HTMLElement>(*node).setInnerText(WTFMove(displayValue));
        return;
    }

    DateTimeEditElement::LayoutParameters layoutParameters(element()->locale());

    auto date = parseToDateComponents(element()->value());
    if (date)
        setupLayoutParameters(layoutParameters, *date);
    else {
        if (auto dateForLayout = setMillisecondToDateComponents(createStepRange(AnyStepHandling::Default).minimum().toDouble()))
            setupLayoutParameters(layoutParameters, *dateForLayout);
        else
            setupLayoutParameters(layoutParameters, DateComponents());
    }

    if (!DateTimeFormatValidator().validateFormat(layoutParameters.dateTimeFormat, *this))
        layoutParameters.dateTimeFormat = layoutParameters.fallbackDateTimeFormat;

    if (date)
        m_dateTimeEditElement->setValueAsDate(layoutParameters, *date);
    else
        m_dateTimeEditElement->setEmptyValue(layoutParameters);
}

bool BaseDateAndTimeInputType::hasCustomFocusLogic() const
{
    if (m_dateTimeEditElement)
        return false;
    return InputType::hasCustomFocusLogic();
}

void BaseDateAndTimeInputType::attributeChanged(const QualifiedName& name)
{
    if (name == maxAttr || name == minAttr) {
        if (auto* element = this->element())
            element->invalidateStyleForSubtree();
    } else if (name == valueAttr) {
        if (auto* element = this->element()) {
            if (!element->hasDirtyValue())
                updateInnerTextValue();
        }
    } else if (name == stepAttr && m_dateTimeEditElement)
        updateInnerTextValue();

    InputType::attributeChanged(name);
}

void BaseDateAndTimeInputType::elementDidBlur()
{
    if (!m_dateTimeEditElement)
        closeDateTimeChooser();
}

void BaseDateAndTimeInputType::detach()
{
    closeDateTimeChooser();
}

bool BaseDateAndTimeInputType::isPresentingAttachedView() const
{
    return !!m_dateTimeChooser;
}

auto BaseDateAndTimeInputType::handleKeydownEvent(KeyboardEvent& event) -> ShouldCallBaseEventHandler
{
    ASSERT(element());
    return BaseClickableWithKeyInputType::handleKeydownEvent(*element(), event);
}

void BaseDateAndTimeInputType::handleKeypressEvent(KeyboardEvent& event)
{
    // The return key should not activate the element, as it conflicts with
    // the key binding to submit a form.
    if (event.charCode() == '\r')
        return;

    ASSERT(element());
    BaseClickableWithKeyInputType::handleKeypressEvent(*element(), event);
}

void BaseDateAndTimeInputType::handleKeyupEvent(KeyboardEvent& event)
{
    BaseClickableWithKeyInputType::handleKeyupEvent(*this, event);
}

void BaseDateAndTimeInputType::handleFocusEvent(Node* oldFocusedNode, FocusDirection direction)
{
    if (!m_dateTimeEditElement) {
        InputType::handleFocusEvent(oldFocusedNode, direction);
        return;
    }

    // If the element contains editable components, the element itself should not
    // be focused. Instead, one of it's children should receive focus.

    if (direction == FocusDirection::Backward) {
        // If the element received focus when going backwards, advance the focus one more time
        // so that this element no longer has focus. In this case, one of the children should
        // not be focused as the element is losing focus entirely.
        if (auto* page = element()->document().page())
            CheckedRef(page->focusController())->advanceFocus(direction, 0);

    } else {
        // If the element received focus in any other direction, transfer focus to the first focusable child.
        m_dateTimeEditElement->focusByOwner();
    }
}

bool BaseDateAndTimeInputType::accessKeyAction(bool sendMouseEvents)
{
    InputType::accessKeyAction(sendMouseEvents);
    ASSERT(element());
    return BaseClickableWithKeyInputType::accessKeyAction(*element(), sendMouseEvents);
}

void BaseDateAndTimeInputType::didBlurFromControl()
{
    closeDateTimeChooser();
}

void BaseDateAndTimeInputType::didChangeValueFromControl()
{
    String value = sanitizeValue(m_dateTimeEditElement->value());
    InputType::setValue(value, value != element()->value(), DispatchInputAndChangeEvent, DoNotSet);

    DateTimeChooserParameters parameters;
    if (!setupDateTimeChooserParameters(parameters))
        return;

    if (m_dateTimeChooser)
        m_dateTimeChooser->showChooser(parameters);
}

bool BaseDateAndTimeInputType::isEditControlOwnerDisabled() const
{
    ASSERT(element());
    return element()->isDisabledFormControl();
}

bool BaseDateAndTimeInputType::isEditControlOwnerReadOnly() const
{
    ASSERT(element());
    return element()->isReadOnly();
}

AtomString BaseDateAndTimeInputType::localeIdentifier() const
{
    ASSERT(element());
    return element()->computeInheritedLanguage();
}

void BaseDateAndTimeInputType::didChooseValue(StringView value)
{
    ASSERT(element());
    element()->setValue(value.toString(), DispatchInputAndChangeEvent);
}

void BaseDateAndTimeInputType::didEndChooser()
{
    m_dateTimeChooser = nullptr;
}

bool BaseDateAndTimeInputType::setupDateTimeChooserParameters(DateTimeChooserParameters& parameters)
{
    ASSERT(element());

    auto& element = *this->element();
    auto& document = element.document();

    if (!document.view())
        return false;

    parameters.type = element.type();
    parameters.minimum = element.minimum();
    parameters.maximum = element.maximum();
    parameters.required = element.isRequired();

    if (!document.settings().langAttributeAwareFormControlUIEnabled())
        parameters.locale = AtomString { defaultLanguage() };
    else {
        AtomString computedLocale = element.computeInheritedLanguage();
        parameters.locale = computedLocale.isEmpty() ? AtomString(defaultLanguage()) : computedLocale;
    }

    auto stepRange = createStepRange(AnyStepHandling::Reject);
    if (stepRange.hasStep()) {
        parameters.step = stepRange.step().toDouble();
        parameters.stepBase = stepRange.stepBase().toDouble();
    } else {
        parameters.step = 1.0;
        parameters.stepBase = 0;
    }

    if (RenderElement* renderer = element.renderer())
        parameters.anchorRectInRootView = document.view()->contentsToRootView(renderer->absoluteBoundingBoxRect());
    else
        parameters.anchorRectInRootView = IntRect();
    parameters.currentValue = element.value();

    auto* computedStyle = element.computedStyle();
    parameters.isAnchorElementRTL = computedStyle->direction() == TextDirection::RTL;
    parameters.useDarkAppearance = document.useDarkAppearance(computedStyle);

    auto date = valueOrDefault(parseToDateComponents(element.value()));
    parameters.hasSecondField = shouldHaveSecondField(date);
    parameters.hasMillisecondField = shouldHaveMillisecondField(date);

#if ENABLE(DATALIST_ELEMENT)
    if (auto dataList = element.dataList()) {
        for (auto& option : dataList->suggestions()) {
            auto label = option.label();
            auto value = option.value();
            if (!element.isValidValue(value))
                continue;
            parameters.suggestionValues.append(element.sanitizeValue(value));
            parameters.localizedSuggestionValues.append(element.localizeValue(value));
            parameters.suggestionLabels.append(value == label ? String() : label);
        }
    }
#endif

    return true;
}

void BaseDateAndTimeInputType::closeDateTimeChooser()
{
    if (m_dateTimeChooser)
        m_dateTimeChooser->endChooser();
}

} // namespace WebCore

#endif
