/*
 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
 *           (C) 1999 Antti Koivisto (koivisto@kde.org)
 *           (C) 2001 Dirk Mueller (mueller@kde.org)
 * Copyright (C) 2004-2019 Apple Inc. All rights reserved.
 *           (C) 2006 Alexey Proskuryakov (ap@nypop.com)
 * Copyright (C) 2007 Samuel Weinig (sam@webkit.org)
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 *
 */

#include "config.h"
#include "HTMLTextAreaElement.h"

#include "BeforeTextInsertedEvent.h"
#include "CSSValueKeywords.h"
#include "DOMFormData.h"
#include "Document.h"
#include "Editor.h"
#include "ElementChildIterator.h"
#include "Event.h"
#include "EventNames.h"
#include "FormController.h"
#include "Frame.h"
#include "FrameSelection.h"
#include "HTMLNames.h"
#include "HTMLParserIdioms.h"
#include "LocalizedStrings.h"
#include "RenderTextControlMultiLine.h"
#include "ShadowRoot.h"
#include "Text.h"
#include "TextControlInnerElements.h"
#include "TextIterator.h"
#include "TextNodeTraversal.h"
#include <wtf/IsoMallocInlines.h>
#include <wtf/Ref.h>
#include <wtf/StdLibExtras.h>

namespace WebCore {

WTF_MAKE_ISO_ALLOCATED_IMPL(HTMLTextAreaElement);

using namespace HTMLNames;

static const int defaultRows = 2;
static const int defaultCols = 20;

// On submission, LF characters are converted into CRLF.
// This function returns number of characters considering this.
static inline unsigned computeLengthForSubmission(StringView text, unsigned numberOfLineBreaks)
{
    return numGraphemeClusters(text) + numberOfLineBreaks;
}

static unsigned numberOfLineBreaks(StringView text)
{
    unsigned length = text.length();
    unsigned count = 0;
    for (unsigned i = 0; i < length; i++) {
        if (text[i] == '\n')
            count++;
    }
    return count;
}

static inline unsigned computeLengthForSubmission(StringView text)
{
    return numGraphemeClusters(text) + numberOfLineBreaks(text);
}

static inline unsigned upperBoundForLengthForSubmission(StringView text, unsigned numberOfLineBreaks)
{
    return text.length() + numberOfLineBreaks;
}

HTMLTextAreaElement::HTMLTextAreaElement(const QualifiedName& tagName, Document& document, HTMLFormElement* form)
    : HTMLTextFormControlElement(tagName, document, form)
    , m_rows(defaultRows)
    , m_cols(defaultCols)
{
    ASSERT(hasTagName(textareaTag));
    setFormControlValueMatchesRenderer(true);
}

Ref<HTMLTextAreaElement> HTMLTextAreaElement::create(const QualifiedName& tagName, Document& document, HTMLFormElement* form)
{
    auto textArea = adoptRef(*new HTMLTextAreaElement(tagName, document, form));
    textArea->ensureUserAgentShadowRoot();
    return textArea;
}

void HTMLTextAreaElement::didAddUserAgentShadowRoot(ShadowRoot& root)
{
    root.appendChild(TextControlInnerTextElement::create(document()));
    updateInnerTextElementEditability();
}

const AtomString& HTMLTextAreaElement::formControlType() const
{
    static NeverDestroyed<const AtomString> textarea("textarea", AtomString::ConstructFromLiteral);
    return textarea;
}

FormControlState HTMLTextAreaElement::saveFormControlState() const
{
    return m_isDirty ? FormControlState { { value() } } : FormControlState { };
}

void HTMLTextAreaElement::restoreFormControlState(const FormControlState& state)
{
    setValue(state[0]);
}

void HTMLTextAreaElement::childrenChanged(const ChildChange& change)
{
    HTMLElement::childrenChanged(change);
    setLastChangeWasNotUserEdit();
    if (m_isDirty)
        setInnerTextValue(value());
    else
        setNonDirtyValue(defaultValue());
}

bool HTMLTextAreaElement::isPresentationAttribute(const QualifiedName& name) const
{
    if (name == alignAttr) {
        // Don't map 'align' attribute.  This matches what Firefox, Opera and IE do.
        // See http://bugs.webkit.org/show_bug.cgi?id=7075
        return false;
    }

    if (name == wrapAttr)
        return true;
    return HTMLTextFormControlElement::isPresentationAttribute(name);
}

void HTMLTextAreaElement::collectStyleForPresentationAttribute(const QualifiedName& name, const AtomString& value, MutableStyleProperties& style)
{
    if (name == wrapAttr) {
        if (shouldWrapText()) {
            addPropertyToPresentationAttributeStyle(style, CSSPropertyWhiteSpace, CSSValuePreWrap);
            addPropertyToPresentationAttributeStyle(style, CSSPropertyWordWrap, CSSValueBreakWord);
        } else {
            addPropertyToPresentationAttributeStyle(style, CSSPropertyWhiteSpace, CSSValuePre);
            addPropertyToPresentationAttributeStyle(style, CSSPropertyWordWrap, CSSValueNormal);
        }
    } else
        HTMLTextFormControlElement::collectStyleForPresentationAttribute(name, value, style);
}

void HTMLTextAreaElement::parseAttribute(const QualifiedName& name, const AtomString& value)
{
    if (name == rowsAttr) {
        unsigned rows = limitToOnlyHTMLNonNegativeNumbersGreaterThanZero(value, defaultRows);
        if (m_rows != rows) {
            m_rows = rows;
            if (renderer())
                renderer()->setNeedsLayoutAndPrefWidthsRecalc();
        }
    } else if (name == colsAttr) {
        unsigned cols = limitToOnlyHTMLNonNegativeNumbersGreaterThanZero(value, defaultCols);
        if (m_cols != cols) {
            m_cols = cols;
            if (renderer())
                renderer()->setNeedsLayoutAndPrefWidthsRecalc();
        }
    } else if (name == wrapAttr) {
        // The virtual/physical values were a Netscape extension of HTML 3.0, now deprecated.
        // The soft/hard /off values are a recommendation for HTML 4 extension by IE and NS 4.
        WrapMethod wrap;
        if (equalLettersIgnoringASCIICase(value, "physical") || equalLettersIgnoringASCIICase(value, "hard") || equalLettersIgnoringASCIICase(value, "on"))
            wrap = HardWrap;
        else if (equalLettersIgnoringASCIICase(value, "off"))
            wrap = NoWrap;
        else
            wrap = SoftWrap;
        if (wrap != m_wrap) {
            m_wrap = wrap;
            if (renderer())
                renderer()->setNeedsLayoutAndPrefWidthsRecalc();
        }
    } else if (name == maxlengthAttr)
        maxLengthAttributeChanged(value);
    else if (name == minlengthAttr)
        minLengthAttributeChanged(value);
    else
        HTMLTextFormControlElement::parseAttribute(name, value);
}

void HTMLTextAreaElement::maxLengthAttributeChanged(const AtomString& newValue)
{
    internalSetMaxLength(parseHTMLNonNegativeInteger(newValue).value_or(-1));
    updateValidity();
}

void HTMLTextAreaElement::minLengthAttributeChanged(const AtomString& newValue)
{
    internalSetMinLength(parseHTMLNonNegativeInteger(newValue).value_or(-1));
    updateValidity();
}

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

bool HTMLTextAreaElement::appendFormData(DOMFormData& formData, bool)
{
    if (name().isEmpty())
        return false;

    Ref<HTMLTextAreaElement> protectedThis(*this);
    document().updateLayout();

    formData.append(name(), m_wrap == HardWrap ? valueWithHardLineBreaks() : value());

    auto& dirnameAttrValue = attributeWithoutSynchronization(dirnameAttr);
    if (!dirnameAttrValue.isNull())
        formData.append(dirnameAttrValue, directionForFormData());

    return true;    
}

void HTMLTextAreaElement::reset()
{
    setNonDirtyValue(defaultValue());
}

bool HTMLTextAreaElement::hasCustomFocusLogic() const
{
    return true;
}

bool HTMLTextAreaElement::isKeyboardFocusable(KeyboardEvent*) const
{
    // If a given text area can be focused at all, then it will always be keyboard focusable.
    return isFocusable();
}

bool HTMLTextAreaElement::isMouseFocusable() const
{
    return isFocusable();
}

void HTMLTextAreaElement::updateFocusAppearance(SelectionRestorationMode restorationMode, SelectionRevealMode revealMode)
{
    if (restorationMode == SelectionRestorationMode::SetDefault || !hasCachedSelection()) {
        // If this is the first focus, set a caret at the beginning of the text.  
        // This matches some browsers' behavior; see bug 11746 Comment #15.
        // http://bugs.webkit.org/show_bug.cgi?id=11746#c15
        setSelectionRange(0, 0, SelectionHasNoDirection, revealMode, Element::defaultFocusTextStateChangeIntent());
    } else
        restoreCachedSelection(revealMode, Element::defaultFocusTextStateChangeIntent());
}

void HTMLTextAreaElement::defaultEventHandler(Event& event)
{
    if (renderer() && (event.isMouseEvent() || event.type() == eventNames().blurEvent))
        forwardEvent(event);
    else if (renderer() && is<BeforeTextInsertedEvent>(event))
        handleBeforeTextInsertedEvent(downcast<BeforeTextInsertedEvent>(event));

    HTMLTextFormControlElement::defaultEventHandler(event);
}

void HTMLTextAreaElement::subtreeHasChanged()
{
    setChangedSinceLastFormControlChangeEvent(true);
    setFormControlValueMatchesRenderer(false);
    updateValidity();

    if (!focused())
        return;

    if (RefPtr<Frame> frame = document().frame())
        frame->editor().textDidChangeInTextArea(this);
    // When typing in a textarea, childrenChanged is not called, so we need to force the directionality check.
    calculateAndAdjustDirectionality();
}

void HTMLTextAreaElement::handleBeforeTextInsertedEvent(BeforeTextInsertedEvent& event) const
{
    ASSERT(renderer());
    int signedMaxLength = effectiveMaxLength();
    if (signedMaxLength < 0)
        return;
    unsigned unsignedMaxLength = static_cast<unsigned>(signedMaxLength);

    const String& currentValue = innerTextValue();
    unsigned numberOfLineBreaksInCurrentValue = numberOfLineBreaks(currentValue);
    if (upperBoundForLengthForSubmission(currentValue, numberOfLineBreaksInCurrentValue)
        + upperBoundForLengthForSubmission(event.text(), numberOfLineBreaks(event.text())) < unsignedMaxLength)
        return;

    unsigned currentLength = computeLengthForSubmission(currentValue, numberOfLineBreaksInCurrentValue);
    // selectionLength represents the selection length of this text field to be
    // removed by this insertion.
    // If the text field has no focus, we don't need to take account of the
    // selection length. The selection is the source of text drag-and-drop in
    // that case, and nothing in the text field will be removed.
    unsigned selectionLength = focused() ? computeLengthForSubmission(plainText(document().frame()->selection().selection().toNormalizedRange().get())) : 0;
    ASSERT(currentLength >= selectionLength);
    unsigned baseLength = currentLength - selectionLength;
    unsigned appendableLength = unsignedMaxLength > baseLength ? unsignedMaxLength - baseLength : 0;
    event.setText(sanitizeUserInputValue(event.text(), appendableLength));
}

String HTMLTextAreaElement::sanitizeUserInputValue(const String& proposedValue, unsigned maxLength)
{
    return proposedValue.left(numCodeUnitsInGraphemeClusters(proposedValue, maxLength));
}

RefPtr<TextControlInnerTextElement> HTMLTextAreaElement::innerTextElement() const
{
    RefPtr<ShadowRoot> root = userAgentShadowRoot();
    if (!root)
        return nullptr;
    
    return childrenOfType<TextControlInnerTextElement>(*root).first();
}

void HTMLTextAreaElement::rendererWillBeDestroyed()
{
    updateValue();
}

void HTMLTextAreaElement::updateValue() const
{
    if (formControlValueMatchesRenderer())
        return;

    ASSERT(renderer());
    m_value = innerTextValue();
    const_cast<HTMLTextAreaElement*>(this)->setFormControlValueMatchesRenderer(true);
    m_isDirty = true;
    m_wasModifiedByUser = true;
    const_cast<HTMLTextAreaElement*>(this)->updatePlaceholderVisibility();
}

String HTMLTextAreaElement::value() const
{
    updateValue();
    return m_value;
}

void HTMLTextAreaElement::setValue(const String& value)
{
    setValueCommon(value);
    m_isDirty = true;
    updateValidity();
}

void HTMLTextAreaElement::setNonDirtyValue(const String& value)
{
    setValueCommon(value);
    m_isDirty = false;
    updateValidity();
}

void HTMLTextAreaElement::setValueCommon(const String& newValue)
{
    m_wasModifiedByUser = false;
    // Code elsewhere normalizes line endings added by the user via the keyboard or pasting.
    // We normalize line endings coming from JavaScript here.
    String normalizedValue = newValue.isNull() ? emptyString() : newValue;
    normalizedValue.replace("\r\n", "\n");
    normalizedValue.replace('\r', '\n');

    // Return early because we don't want to move the caret or trigger other side effects
    // when the value isn't changing. This matches Firefox behavior, at least.
    if (normalizedValue == value())
        return;

    m_value = normalizedValue;
    setInnerTextValue(m_value);
    setLastChangeWasNotUserEdit();
    updatePlaceholderVisibility();
    invalidateStyleForSubtree();
    setFormControlValueMatchesRenderer(true);

    // Set the caret to the end of the text value.
    if (document().focusedElement() == this) {
        unsigned endOfString = m_value.length();
        setSelectionRange(endOfString, endOfString);
    }

    setTextAsOfLastFormControlChangeEvent(normalizedValue);
}

String HTMLTextAreaElement::defaultValue() const
{
    return TextNodeTraversal::childTextContent(*this);
}

void HTMLTextAreaElement::setDefaultValue(const String& defaultValue)
{
    setTextContent(defaultValue);
}

String HTMLTextAreaElement::validationMessage() const
{
    if (!willValidate())
        return String();

    if (customError())
        return customValidationMessage();

    if (valueMissing())
        return validationMessageValueMissingText();

    if (tooShort())
        return validationMessageTooShortText(computeLengthForSubmission(value()), minLength());

    if (tooLong())
        return validationMessageTooLongText(computeLengthForSubmission(value()), effectiveMaxLength());

    return String();
}

bool HTMLTextAreaElement::valueMissing() const
{
    return willValidate() && valueMissing(value());
}

bool HTMLTextAreaElement::tooShort() const
{
    return willValidate() && tooShort(value(), CheckDirtyFlag);
}

bool HTMLTextAreaElement::tooShort(StringView value, NeedsToCheckDirtyFlag check) const
{
    // Return false for the default value or value set by script even if it is
    // shorter than minLength.
    if (check == CheckDirtyFlag && !m_wasModifiedByUser)
        return false;

    int min = minLength();
    if (min <= 0)
        return false;

    // The empty string is excluded from tooShort validation.
    if (value.isEmpty())
        return false;

    // FIXME: The HTML specification says that the "number of characters" is measured using code-unit length and,
    // in the case of textarea elements, with all line breaks normalized to a single character (as opposed to CRLF pairs).
    unsigned unsignedMin = static_cast<unsigned>(min);
    unsigned numberOfLineBreaksInValue = numberOfLineBreaks(value);
    return upperBoundForLengthForSubmission(value, numberOfLineBreaksInValue) < unsignedMin
        && computeLengthForSubmission(value, numberOfLineBreaksInValue) < unsignedMin;
}

bool HTMLTextAreaElement::tooLong() const
{
    return willValidate() && tooLong(value(), CheckDirtyFlag);
}

bool HTMLTextAreaElement::tooLong(StringView value, NeedsToCheckDirtyFlag check) const
{
    // Return false for the default value or value set by script even if it is
    // longer than maxLength.
    if (check == CheckDirtyFlag && !m_wasModifiedByUser)
        return false;

    int max = effectiveMaxLength();
    if (max < 0)
        return false;

    // FIXME: The HTML specification says that the "number of characters" is measured using code-unit length and,
    // in the case of textarea elements, with all line breaks normalized to a single character (as opposed to CRLF pairs).
    unsigned unsignedMax = static_cast<unsigned>(max);
    unsigned numberOfLineBreaksInValue = numberOfLineBreaks(value);
    return upperBoundForLengthForSubmission(value, numberOfLineBreaksInValue) > unsignedMax
        && computeLengthForSubmission(value, numberOfLineBreaksInValue) > unsignedMax;
}

bool HTMLTextAreaElement::isValidValue(const String& candidate) const
{
    return !valueMissing(candidate) && !tooShort(candidate, IgnoreDirtyFlag) && !tooLong(candidate, IgnoreDirtyFlag);
}

void HTMLTextAreaElement::accessKeyAction(bool)
{
    focus();
}

void HTMLTextAreaElement::setCols(unsigned cols)
{
    setUnsignedIntegralAttribute(colsAttr, limitToOnlyHTMLNonNegativeNumbersGreaterThanZero(cols, defaultCols));
}

void HTMLTextAreaElement::setRows(unsigned rows)
{
    setUnsignedIntegralAttribute(rowsAttr, limitToOnlyHTMLNonNegativeNumbersGreaterThanZero(rows, defaultRows));
}

bool HTMLTextAreaElement::shouldUseInputMethod()
{
    return true;
}

HTMLElement* HTMLTextAreaElement::placeholderElement() const
{
    return m_placeholder.get();
}

bool HTMLTextAreaElement::matchesReadWritePseudoClass() const
{
    return !isDisabledOrReadOnly();
}

void HTMLTextAreaElement::updatePlaceholderText()
{
    String placeholderText = strippedPlaceholder();
    if (placeholderText.isEmpty()) {
        if (m_placeholder) {
            userAgentShadowRoot()->removeChild(*m_placeholder);
            m_placeholder = nullptr;
        }
        return;
    }
    if (!m_placeholder) {
        m_placeholder = TextControlPlaceholderElement::create(document());
        userAgentShadowRoot()->insertBefore(*m_placeholder, innerTextElement()->nextSibling());
    }
    m_placeholder->setInnerText(placeholderText);
}

bool HTMLTextAreaElement::willRespondToMouseClickEvents()
{
    return !isDisabledFormControl();
}

RenderStyle HTMLTextAreaElement::createInnerTextStyle(const RenderStyle& style)
{
    auto textBlockStyle = RenderStyle::create();
    textBlockStyle.inheritFrom(style);
    adjustInnerTextStyle(style, textBlockStyle);
    textBlockStyle.setDisplay(DisplayType::Block);
    return textBlockStyle;
}

void HTMLTextAreaElement::copyNonAttributePropertiesFromElement(const Element& source)
{
    auto& sourceElement = downcast<HTMLTextAreaElement>(source);

    setValueCommon(sourceElement.value());
    m_isDirty = sourceElement.m_isDirty;
    HTMLTextFormControlElement::copyNonAttributePropertiesFromElement(source);

    updateValidity();
}

} // namespace WebCore
