/*
 * Copyright (C) 2004-2007, 2016 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:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 APPLE INC. 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 "Editing.h"

#include "AXObjectCache.h"
#include "CachedImage.h"
#include "Document.h"
#include "Editor.h"
#include "Frame.h"
#include "HTMLBodyElement.h"
#include "HTMLDListElement.h"
#include "HTMLDivElement.h"
#include "HTMLElementFactory.h"
#include "HTMLImageElement.h"
#include "HTMLInterchange.h"
#include "HTMLLIElement.h"
#include "HTMLNames.h"
#include "HTMLOListElement.h"
#include "HTMLParagraphElement.h"
#include "HTMLSpanElement.h"
#include "HTMLTableElement.h"
#include "HTMLTextFormControlElement.h"
#include "HTMLUListElement.h"
#include "NodeTraversal.h"
#include "PositionIterator.h"
#include "RenderBlock.h"
#include "RenderElement.h"
#include "RenderTableCell.h"
#include "ShadowRoot.h"
#include "Text.h"
#include "TextIterator.h"
#include "VisibleUnits.h"
#include <wtf/Assertions.h>
#include <wtf/StdLibExtras.h>
#include <wtf/text/StringBuilder.h>
#include <wtf/unicode/CharacterNames.h>

namespace WebCore {

using namespace HTMLNames;

static bool isVisiblyAdjacent(const Position&, const Position&);

bool canHaveChildrenForEditing(const Node& node)
{
    return !is<Text>(node) && node.canContainRangeEndPoint();
}

// Atomic means that the node has no children, or has children which are ignored for the purposes of editing.
bool isAtomicNode(const Node* node)
{
    return node && (!node->hasChildNodes() || editingIgnoresContent(*node));
}

// Compare two positions, taking into account the possibility that one or both
// could be inside a shadow tree. Only works for non-null values.
int comparePositions(const Position& a, const Position& b)
{
    TreeScope* commonScope = commonTreeScope(a.containerNode(), b.containerNode());

    if (!commonScope)
        return 0;

    Node* nodeA = commonScope->ancestorNodeInThisScope(a.containerNode());
    ASSERT(nodeA);
    bool hasDescendentA = nodeA != a.containerNode();
    int offsetA = hasDescendentA ? 0 : a.computeOffsetInContainerNode();

    Node* nodeB = commonScope->ancestorNodeInThisScope(b.containerNode());
    ASSERT(nodeB);
    bool hasDescendentB = nodeB != b.containerNode();
    int offsetB = hasDescendentB ? 0 : b.computeOffsetInContainerNode();

    int bias = 0;
    if (nodeA == nodeB) {
        if (hasDescendentA)
            bias = -1;
        else if (hasDescendentB)
            bias = 1;
    }

    auto comparisonResult = Range::compareBoundaryPoints(nodeA, offsetA, nodeB, offsetB);
    if (comparisonResult.hasException())
        return bias;
    auto result = comparisonResult.releaseReturnValue();
    return result ? result : bias;
}

int comparePositions(const VisiblePosition& a, const VisiblePosition& b)
{
    return comparePositions(a.deepEquivalent(), b.deepEquivalent());
}

ContainerNode* highestEditableRoot(const Position& position, EditableType editableType)
{
    ContainerNode* highestEditableRoot = editableRootForPosition(position, editableType);
    if (!highestEditableRoot)
        return nullptr;

    for (ContainerNode* node = highestEditableRoot; !is<HTMLBodyElement>(*node); ) {
        node = node->parentNode();
        if (!node)
            break;
        // FIXME: Can this ever be a Document or DocumentFragment? If not, this should return Element* instead.
        if (hasEditableStyle(*node, editableType))
            highestEditableRoot = node;
    }

    return highestEditableRoot;
}

Element* lowestEditableAncestor(Node* node)
{
    for (; node; node = node->parentNode()) {
        if (node->hasEditableStyle())
            return node->rootEditableElement();
        if (is<HTMLBodyElement>(*node))
            break;
    }
    return nullptr;
}

static bool isEditableToAccessibility(const Node& node)
{
    ASSERT(AXObjectCache::accessibilityEnabled());
    ASSERT(node.document().existingAXObjectCache());

    if (auto* cache = node.document().existingAXObjectCache())
        return cache->rootAXEditableElement(&node);

    return false;
}

static bool computeEditability(const Node& node, EditableType editableType, Node::ShouldUpdateStyle shouldUpdateStyle)
{
    if (node.computeEditability(Node::UserSelectAllIsAlwaysNonEditable, shouldUpdateStyle) != Node::Editability::ReadOnly)
        return true;

    switch (editableType) {
    case ContentIsEditable:
        return false;
    case HasEditableAXRole:
        return isEditableToAccessibility(node);
    }
    ASSERT_NOT_REACHED();
    return false;
}

bool hasEditableStyle(const Node& node, EditableType editableType)
{
    return computeEditability(node, editableType, Node::ShouldUpdateStyle::DoNotUpdate);
}

bool isEditableNode(const Node& node)
{
    return computeEditability(node, ContentIsEditable, Node::ShouldUpdateStyle::Update);
}

bool isEditablePosition(const Position& position, EditableType editableType)
{
    Node* node = position.containerNode();
    return node && computeEditability(*node, editableType, Node::ShouldUpdateStyle::Update);
}

bool isAtUnsplittableElement(const Position& position)
{
    Node* node = position.containerNode();
    return node == editableRootForPosition(position) || node == enclosingNodeOfType(position, isTableCell);
}

bool isRichlyEditablePosition(const Position& position)
{
    auto* node = position.containerNode();
    return node && node->hasRichlyEditableStyle();
}

Element* editableRootForPosition(const Position& position, EditableType editableType)
{
    Node* node = position.containerNode();
    if (!node)
        return nullptr;

    switch (editableType) {
    case HasEditableAXRole:
        if (auto* cache = node->document().existingAXObjectCache())
            return const_cast<Element*>(cache->rootAXEditableElement(node));
        FALLTHROUGH;
    case ContentIsEditable:
        return node->rootEditableElement();
    }
    return nullptr;
}

// Finds the enclosing element until which the tree can be split.
// When a user hits ENTER, he/she won't expect this element to be split into two.
// You may pass it as the second argument of splitTreeToNode.
Element* unsplittableElementForPosition(const Position& position)
{
    // Since enclosingNodeOfType won't search beyond the highest root editable node,
    // this code works even if the closest table cell was outside of the root editable node.
    if (auto* enclosingCell = downcast<Element>(enclosingNodeOfType(position, &isTableCell)))
        return enclosingCell;
    return editableRootForPosition(position);
}

Position nextCandidate(const Position& position)
{
    for (PositionIterator nextPosition = position; !nextPosition.atEnd(); ) {
        nextPosition.increment();
        if (nextPosition.isCandidate())
            return nextPosition;
    }
    return { };
}

Position nextVisuallyDistinctCandidate(const Position& position)
{
    // FIXME: Use PositionIterator instead.
    Position nextPosition = position;
    Position downstreamStart = nextPosition.downstream();
    while (!nextPosition.atEndOfTree()) {
        nextPosition = nextPosition.next(Character);
        if (nextPosition.isCandidate() && nextPosition.downstream() != downstreamStart)
            return nextPosition;
        if (auto* node = nextPosition.containerNode()) {
            if (!node->renderer())
                nextPosition = lastPositionInOrAfterNode(node);
        }
    }
    return { };
}

Position previousCandidate(const Position& position)
{
    PositionIterator previousPosition = position;
    while (!previousPosition.atStart()) {
        previousPosition.decrement();
        if (previousPosition.isCandidate())
            return previousPosition;
    }
    return { };
}

Position previousVisuallyDistinctCandidate(const Position& position)
{
    // FIXME: Use PositionIterator instead.
    Position previousPosition = position;
    Position downstreamStart = previousPosition.downstream();
    while (!previousPosition.atStartOfTree()) {
        previousPosition = previousPosition.previous(Character);
        if (previousPosition.isCandidate() && previousPosition.downstream() != downstreamStart)
            return previousPosition;
        if (auto* node = previousPosition.containerNode()) {
            if (!node->renderer())
                previousPosition = firstPositionInOrBeforeNode(node);
        }
    }
    return { };
}

Position firstEditablePositionAfterPositionInRoot(const Position& position, ContainerNode* highestRoot)
{
    if (!highestRoot)
        return { };

    // position falls before highestRoot.
    if (comparePositions(position, firstPositionInNode(highestRoot)) == -1 && highestRoot->hasEditableStyle())
        return firstPositionInNode(highestRoot);

    Position candidate = position;

    if (&position.deprecatedNode()->treeScope() != &highestRoot->treeScope()) {
        auto* shadowAncestor = highestRoot->treeScope().ancestorNodeInThisScope(position.deprecatedNode());
        if (!shadowAncestor)
            return { };

        candidate = positionAfterNode(shadowAncestor);
    }

    while (candidate.deprecatedNode() && !isEditablePosition(candidate) && candidate.deprecatedNode()->isDescendantOf(*highestRoot))
        candidate = isAtomicNode(candidate.deprecatedNode()) ? positionInParentAfterNode(candidate.deprecatedNode()) : nextVisuallyDistinctCandidate(candidate);

    if (candidate.deprecatedNode() && candidate.deprecatedNode() != highestRoot && !candidate.deprecatedNode()->isDescendantOf(*highestRoot))
        return { };

    return candidate;
}

Position lastEditablePositionBeforePositionInRoot(const Position& position, ContainerNode* highestRoot)
{
    if (!highestRoot)
        return { };

    // When position falls after highestRoot, the result is easy to compute.
    if (comparePositions(position, lastPositionInNode(highestRoot)) == 1)
        return lastPositionInNode(highestRoot);

    Position candidate = position;

    if (&position.deprecatedNode()->treeScope() != &highestRoot->treeScope()) {
        auto* shadowAncestor = highestRoot->treeScope().ancestorNodeInThisScope(position.deprecatedNode());
        if (!shadowAncestor)
            return { };

        candidate = firstPositionInOrBeforeNode(shadowAncestor);
    }

    while (candidate.deprecatedNode() && !isEditablePosition(candidate) && candidate.deprecatedNode()->isDescendantOf(*highestRoot))
        candidate = isAtomicNode(candidate.deprecatedNode()) ? positionInParentBeforeNode(candidate.deprecatedNode()) : previousVisuallyDistinctCandidate(candidate);
    
    if (candidate.deprecatedNode() && candidate.deprecatedNode() != highestRoot && !candidate.deprecatedNode()->isDescendantOf(*highestRoot))
        return { };
    
    return candidate;
}

// FIXME: The function name, comment, and code say three different things here!
// Whether or not content before and after this node will collapse onto the same line as it.
bool isBlock(const Node* node)
{
    return node && node->renderer() && !node->renderer()->isInline() && !node->renderer()->isRubyText();
}

bool isInline(const Node* node)
{
    return node && node->renderer() && node->renderer()->isInline();
}

// FIXME: Deploy this in all of the places where enclosingBlockFlow/enclosingBlockFlowOrTableElement are used.
// FIXME: Pass a position to this function. The enclosing block of [table, x] for example, should be the 
// block that contains the table and not the table, and this function should be the only one responsible for 
// knowing about these kinds of special cases.
Element* enclosingBlock(Node* node, EditingBoundaryCrossingRule rule)
{
    Node* enclosingNode = enclosingNodeOfType(firstPositionInOrBeforeNode(node), isBlock, rule);
    return is<Element>(enclosingNode) ? downcast<Element>(enclosingNode) : nullptr;
}

TextDirection directionOfEnclosingBlock(const Position& position)
{
    auto block = enclosingBlock(position.containerNode());
    if (!block)
        return TextDirection::LTR;
    auto renderer = block->renderer();
    if (!renderer)
        return TextDirection::LTR;
    return renderer->style().direction();
}

// This method is used to create positions in the DOM. It returns the maximum valid offset
// in a node. It returns 1 for some elements even though they do not have children, which
// creates technically invalid DOM Positions. Be sure to call parentAnchoredEquivalent
// on a Position before using it to create a DOM Range, or an exception will be thrown.
int lastOffsetForEditing(const Node& node)
{
    if (node.isCharacterDataNode())
        return node.maxCharacterOffset();

    if (node.hasChildNodes())
        return node.countChildNodes();

    // NOTE: This should preempt the countChildNodes() for, e.g., select nodes.
    // FIXME: What does the comment above mean?
    if (editingIgnoresContent(node))
        return 1;

    return 0;
}

bool isAmbiguousBoundaryCharacter(UChar character)
{
    // These are characters that can behave as word boundaries, but can appear within words.
    // If they are just typed, i.e. if they are immediately followed by a caret, we want to delay text checking until the next character has been typed.
    // FIXME: this is required until <rdar://problem/6853027> is fixed and text checking can do this for us.
    return character == '\'' || character == '@' || character == rightSingleQuotationMark || character == hebrewPunctuationGershayim;
}

String stringWithRebalancedWhitespace(const String& string, bool startIsStartOfParagraph, bool endIsEndOfParagraph)
{
    StringBuilder rebalancedString;

    bool previousCharacterWasSpace = false;
    unsigned length = string.length();
    for (unsigned i = 0; i < length; ++i) {
        auto character = string[i];
        if (!deprecatedIsEditingWhitespace(character)) {
            previousCharacterWasSpace = false;
            continue;
        }
        LChar selectedWhitespaceCharacter;
        if (previousCharacterWasSpace || (!i && startIsStartOfParagraph) || (i == length - 1 && endIsEndOfParagraph)) {
            selectedWhitespaceCharacter = noBreakSpace;
            previousCharacterWasSpace = false;
        } else {
            selectedWhitespaceCharacter = ' ';
            previousCharacterWasSpace = true;
        }
        if (character == selectedWhitespaceCharacter)
            continue;
        rebalancedString.reserveCapacity(length);
        rebalancedString.appendSubstring(string, rebalancedString.length(), i - rebalancedString.length());
        rebalancedString.append(selectedWhitespaceCharacter);
    }

    if (rebalancedString.isEmpty())
        return string;

    rebalancedString.reserveCapacity(length);
    rebalancedString.appendSubstring(string, rebalancedString.length(), length - rebalancedString.length());
    return rebalancedString.toString();
}

bool isTableStructureNode(const Node* node)
{
    auto* renderer = node->renderer();
    return renderer && (renderer->isTableCell() || renderer->isTableRow() || renderer->isTableSection() || renderer->isRenderTableCol());
}

const String& nonBreakingSpaceString()
{
    static NeverDestroyed<String> nonBreakingSpaceString(&noBreakSpace, 1);
    return nonBreakingSpaceString;
}

static bool isSpecialHTMLElement(const Node* node)
{
    if (!is<HTMLElement>(node))
        return false;

    if (downcast<HTMLElement>(*node).isLink())
        return true;

    auto* renderer = downcast<HTMLElement>(*node).renderer();
    if (!renderer)
        return false;

    if (renderer->style().display() == DisplayType::Table || renderer->style().display() == DisplayType::InlineTable)
        return true;

    if (renderer->style().isFloating())
        return true;

    if (renderer->style().position() != PositionType::Static)
        return true;

    return false;
}

static HTMLElement* firstInSpecialElement(const Position& position)
{
    auto* rootEditableElement = position.containerNode()->rootEditableElement();
    for (Node* node = position.deprecatedNode(); node && node->rootEditableElement() == rootEditableElement; node = node->parentNode()) {
        if (!isSpecialHTMLElement(node))
            continue;
        VisiblePosition vPos(position, DOWNSTREAM);
        VisiblePosition firstInElement(firstPositionInOrBeforeNode(node), DOWNSTREAM);
        if ((isRenderedTable(node) && vPos == firstInElement.next()) || vPos == firstInElement)
            return &downcast<HTMLElement>(*node);
    }
    return nullptr;
}

static HTMLElement* lastInSpecialElement(const Position& position)
{
    auto* rootEditableElement = position.containerNode()->rootEditableElement();
    for (Node* node = position.deprecatedNode(); node && node->rootEditableElement() == rootEditableElement; node = node->parentNode()) {
        if (!isSpecialHTMLElement(node))
            continue;
        VisiblePosition vPos(position, DOWNSTREAM);
        VisiblePosition lastInElement(lastPositionInOrAfterNode(node), DOWNSTREAM);
        if ((isRenderedTable(node) && vPos == lastInElement.previous()) || vPos == lastInElement)
            return &downcast<HTMLElement>(*node);
    }
    return nullptr;
}

Position positionBeforeContainingSpecialElement(const Position& position, HTMLElement** containingSpecialElement)
{
    auto* element = firstInSpecialElement(position);
    if (!element)
        return position;
    Position result = positionInParentBeforeNode(element);
    if (result.isNull() || result.deprecatedNode()->rootEditableElement() != position.deprecatedNode()->rootEditableElement())
        return position;
    if (containingSpecialElement)
        *containingSpecialElement = element;
    return result;
}

Position positionAfterContainingSpecialElement(const Position& position, HTMLElement** containingSpecialElement)
{
    auto* element = lastInSpecialElement(position);
    if (!element)
        return position;
    Position result = positionInParentAfterNode(element);
    if (result.isNull() || result.deprecatedNode()->rootEditableElement() != position.deprecatedNode()->rootEditableElement())
        return position;
    if (containingSpecialElement)
        *containingSpecialElement = element;
    return result;
}

Element* isFirstPositionAfterTable(const VisiblePosition& position)
{
    Position upstream(position.deepEquivalent().upstream());
    auto* node = upstream.deprecatedNode();
    if (!node)
        return nullptr;
    auto* renderer = node->renderer();
    if (!renderer || !renderer->isTable() || !upstream.atLastEditingPositionForNode())
        return nullptr;
    return &downcast<Element>(*node);
}

Element* isLastPositionBeforeTable(const VisiblePosition& position)
{
    Position downstream(position.deepEquivalent().downstream());
    auto* node = downstream.deprecatedNode();
    if (!node)
        return nullptr;
    auto* renderer = node->renderer();
    if (!renderer || !renderer->isTable() || !downstream.atFirstEditingPositionForNode())
        return nullptr;
    return &downcast<Element>(*node);
}

// Returns the visible position at the beginning of a node
VisiblePosition visiblePositionBeforeNode(Node& node)
{
    if (node.hasChildNodes())
        return VisiblePosition(firstPositionInOrBeforeNode(&node), DOWNSTREAM);
    ASSERT(node.parentNode());
    ASSERT(!node.parentNode()->isShadowRoot());
    return positionInParentBeforeNode(&node);
}

// Returns the visible position at the ending of a node
VisiblePosition visiblePositionAfterNode(Node& node)
{
    if (node.hasChildNodes())
        return VisiblePosition(lastPositionInOrAfterNode(&node), DOWNSTREAM);
    ASSERT(node.parentNode());
    ASSERT(!node.parentNode()->isShadowRoot());
    return positionInParentAfterNode(&node);
}

bool isListHTMLElement(Node* node)
{
    return node && (is<HTMLUListElement>(*node) || is<HTMLOListElement>(*node) || is<HTMLDListElement>(*node));
}

bool isListItem(const Node* node)
{
    return node && (isListHTMLElement(node->parentNode()) || (node->renderer() && node->renderer()->isListItem()));
}

Element* enclosingElementWithTag(const Position& position, const QualifiedName& tagName)
{
    auto* root = highestEditableRoot(position);
    for (Node* node = position.deprecatedNode(); node; node = node->parentNode()) {
        if (root && !node->hasEditableStyle())
            continue;
        if (!is<Element>(*node))
            continue;
        if (downcast<Element>(*node).hasTagName(tagName))
            return &downcast<Element>(*node);
        if (node == root)
            return nullptr;
    }
    return nullptr;
}

Node* enclosingNodeOfType(const Position& position, bool (*nodeIsOfType)(const Node*), EditingBoundaryCrossingRule rule)
{
    // FIXME: support CanSkipCrossEditingBoundary
    ASSERT(rule == CanCrossEditingBoundary || rule == CannotCrossEditingBoundary);
    auto* root = rule == CannotCrossEditingBoundary ? highestEditableRoot(position) : nullptr;
    for (Node* n = position.deprecatedNode(); n; n = n->parentNode()) {
        // Don't return a non-editable node if the input position was editable, since
        // the callers from editing will no doubt want to perform editing inside the returned node.
        if (root && !n->hasEditableStyle())
            continue;
        if (nodeIsOfType(n))
            return n;
        if (n == root)
            return nullptr;
    }
    return nullptr;
}

Node* highestEnclosingNodeOfType(const Position& position, bool (*nodeIsOfType)(const Node*), EditingBoundaryCrossingRule rule, Node* stayWithin)
{
    Node* highest = nullptr;
    auto* root = rule == CannotCrossEditingBoundary ? highestEditableRoot(position) : nullptr;
    for (Node* n = position.containerNode(); n && n != stayWithin; n = n->parentNode()) {
        if (root && !n->hasEditableStyle())
            continue;
        if (nodeIsOfType(n))
            highest = n;
        if (n == root)
            break;
    }
    return highest;
}

static bool hasARenderedDescendant(Node* node, Node* excludedNode)
{
    for (Node* n = node->firstChild(); n;) {
        if (n == excludedNode) {
            n = NodeTraversal::nextSkippingChildren(*n, node);
            continue;
        }
        if (n->renderer())
            return true;
        n = NodeTraversal::next(*n, node);
    }
    return false;
}

Node* highestNodeToRemoveInPruning(Node* node)
{
    Node* previousNode = nullptr;
    auto* rootEditableElement = node ? node->rootEditableElement() : nullptr;
    for (; node; node = node->parentNode()) {
        if (auto* renderer = node->renderer()) {
            if (!renderer->canHaveChildren() || hasARenderedDescendant(node, previousNode) || rootEditableElement == node)
                return previousNode;
        }
        previousNode = node;
    }
    return nullptr;
}

Element* enclosingTableCell(const Position& position)
{
    return downcast<Element>(enclosingNodeOfType(position, isTableCell));
}

Element* enclosingAnchorElement(const Position& p)
{
    for (Node* node = p.deprecatedNode(); node; node = node->parentNode()) {
        if (is<Element>(*node) && node->isLink())
            return downcast<Element>(node);
    }
    return nullptr;
}

HTMLElement* enclosingList(Node* node)
{
    if (!node)
        return nullptr;
        
    auto* root = highestEditableRoot(firstPositionInOrBeforeNode(node));
    
    for (ContainerNode* ancestor = node->parentNode(); ancestor; ancestor = ancestor->parentNode()) {
        if (is<HTMLUListElement>(*ancestor) || is<HTMLOListElement>(*ancestor))
            return downcast<HTMLElement>(ancestor);
        if (ancestor == root)
            return nullptr;
    }
    
    return nullptr;
}

Node* enclosingListChild(Node *node)
{
    if (!node)
        return nullptr;

    // Check for a list item element, or for a node whose parent is a list element. Such a node
    // will appear visually as a list item (but without a list marker)
    auto* root = highestEditableRoot(firstPositionInOrBeforeNode(node));
    
    // FIXME: This function is inappropriately named since it starts with node instead of node->parentNode()
    for (Node* n = node; n && n->parentNode(); n = n->parentNode()) {
        if (is<HTMLLIElement>(*n) || (isListHTMLElement(n->parentNode()) && n != root))
            return n;
        if (n == root || isTableCell(n))
            return nullptr;
    }

    return nullptr;
}

static HTMLElement* embeddedSublist(Node* listItem)
{
    // Check the DOM so that we'll find collapsed sublists without renderers.
    for (Node* n = listItem->firstChild(); n; n = n->nextSibling()) {
        if (isListHTMLElement(n))
            return downcast<HTMLElement>(n);
    }
    return nullptr;
}

static Node* appendedSublist(Node* listItem)
{
    // Check the DOM so that we'll find collapsed sublists without renderers.
    for (Node* n = listItem->nextSibling(); n; n = n->nextSibling()) {
        if (isListHTMLElement(n))
            return downcast<HTMLElement>(n);
        if (isListItem(listItem))
            return nullptr;
    }
    
    return nullptr;
}

// FIXME: This function should not need to call isStartOfParagraph/isEndOfParagraph.
Node* enclosingEmptyListItem(const VisiblePosition& position)
{
    // Check that position is on a line by itself inside a list item
    auto* listChildNode = enclosingListChild(position.deepEquivalent().deprecatedNode());
    if (!listChildNode || !isStartOfParagraph(position) || !isEndOfParagraph(position))
        return nullptr;

    VisiblePosition firstInListChild(firstPositionInOrBeforeNode(listChildNode));
    VisiblePosition lastInListChild(lastPositionInOrAfterNode(listChildNode));

    if (firstInListChild != position || lastInListChild != position)
        return nullptr;

    if (embeddedSublist(listChildNode) || appendedSublist(listChildNode))
        return nullptr;

    return listChildNode;
}

HTMLElement* outermostEnclosingList(Node* node, Node* rootList)
{
    auto* list = enclosingList(node);
    if (!list)
        return nullptr;

    while (auto* nextList = enclosingList(list)) {
        if (nextList == rootList)
            break;
        list = nextList;
    }

    return list;
}

bool canMergeLists(Element* firstList, Element* secondList)
{
    if (!is<HTMLElement>(firstList) || !is<HTMLElement>(secondList))
        return false;

    auto& first = downcast<HTMLElement>(*firstList);
    auto& second = downcast<HTMLElement>(*secondList);

    return first.localName() == second.localName() // make sure the list types match (ol vs. ul)
        && first.hasEditableStyle() && second.hasEditableStyle() // both lists are editable
        && first.rootEditableElement() == second.rootEditableElement() // don't cross editing boundaries
        // Make sure there is no visible content between this li and the previous list.
        && isVisiblyAdjacent(positionInParentAfterNode(&first), positionInParentBeforeNode(&second));
}

static Node* previousNodeConsideringAtomicNodes(const Node* node)
{
    if (node->previousSibling()) {
        Node* n = node->previousSibling();
        while (!isAtomicNode(n) && n->lastChild())
            n = n->lastChild();
        return n;
    }
    if (node->parentNode())
        return node->parentNode();
    return nullptr;
}

static Node* nextNodeConsideringAtomicNodes(const Node* node)
{
    if (!isAtomicNode(node) && node->firstChild())
        return node->firstChild();
    if (node->nextSibling())
        return node->nextSibling();
    const Node* n = node;
    while (n && !n->nextSibling())
        n = n->parentNode();
    if (n)
        return n->nextSibling();
    return nullptr;
}

Node* previousLeafNode(const Node* node)
{
    while ((node = previousNodeConsideringAtomicNodes(node))) {
        if (isAtomicNode(node))
            return const_cast<Node*>(node);
    }
    return nullptr;
}

Node* nextLeafNode(const Node* node)
{
    while ((node = nextNodeConsideringAtomicNodes(node))) {
        if (isAtomicNode(node))
            return const_cast<Node*>(node);
    }
    return nullptr;
}

// FIXME: Do not require renderer, so that this can be used within fragments.
bool isRenderedTable(const Node* node)
{
    if (!is<Element>(node))
        return false;
    auto* renderer = downcast<Element>(*node).renderer();
    return renderer && renderer->isTable();
}

bool isTableCell(const Node* node)
{
    auto* renderer = node->renderer();
    if (!renderer)
        return node->hasTagName(tdTag) || node->hasTagName(thTag);
    return renderer->isTableCell();
}

bool isEmptyTableCell(const Node* node)
{
    // Returns true IFF the passed in node is one of:
    //   .) a table cell with no children,
    //   .) a table cell with a single BR child, and which has no other child renderers, including :before and :after renderers
    //   .) the BR child of such a table cell

    // Find rendered node
    while (node && !node->renderer())
        node = node->parentNode();
    if (!node)
        return false;

    // Make sure the rendered node is a table cell or <br>.
    // If it's a <br>, then the parent node has to be a table cell.
    auto* renderer = node->renderer();
    if (renderer->isBR()) {
        renderer = renderer->parent();
        if (!renderer)
            return false;
    }
    if (!is<RenderTableCell>(*renderer))
        return false;

    // Check that the table cell contains no child renderers except for perhaps a single <br>.
    auto* childRenderer = downcast<RenderTableCell>(*renderer).firstChild();
    if (!childRenderer)
        return true;
    if (!childRenderer->isBR())
        return false;
    return !childRenderer->nextSibling();
}

Ref<HTMLElement> createDefaultParagraphElement(Document& document)
{
    switch (document.frame()->editor().defaultParagraphSeparator()) {
    case EditorParagraphSeparatorIsDiv:
        return HTMLDivElement::create(document);
    case EditorParagraphSeparatorIsP:
        break;
    }
    return HTMLParagraphElement::create(document);
}

Ref<HTMLElement> createHTMLElement(Document& document, const QualifiedName& name)
{
    return HTMLElementFactory::createElement(name, document);
}

Ref<HTMLElement> createHTMLElement(Document& document, const AtomString& tagName)
{
    return createHTMLElement(document, QualifiedName(nullAtom(), tagName, xhtmlNamespaceURI));
}

bool isTabSpanNode(const Node* node)
{
    return is<HTMLSpanElement>(node) && downcast<HTMLSpanElement>(*node).attributeWithoutSynchronization(classAttr) == AppleTabSpanClass;
}

bool isTabSpanTextNode(const Node* node)
{
    return is<Text>(node) && isTabSpanNode(node->parentNode());
}

HTMLSpanElement* tabSpanNode(const Node* node)
{
    return isTabSpanTextNode(node) ? downcast<HTMLSpanElement>(node->parentNode()) : nullptr;
}

static Ref<Element> createTabSpanElement(Document& document, Text& tabTextNode)
{
    auto spanElement = HTMLSpanElement::create(document);

    spanElement->setAttributeWithoutSynchronization(classAttr, AppleTabSpanClass);
    spanElement->setAttribute(styleAttr, "white-space:pre");

    spanElement->appendChild(tabTextNode);

    return spanElement;
}

Ref<Element> createTabSpanElement(Document& document, const String& tabText)
{
    return createTabSpanElement(document, document.createTextNode(tabText));
}

Ref<Element> createTabSpanElement(Document& document)
{
    return createTabSpanElement(document, document.createEditingTextNode("\t"_s));
}

bool isNodeRendered(const Node& node)
{
    auto* renderer = node.renderer();
    return renderer && renderer->style().visibility() == Visibility::Visible;
}

unsigned numEnclosingMailBlockquotes(const Position& position)
{
    unsigned count = 0;
    for (Node* node = position.deprecatedNode(); node; node = node->parentNode()) {
        if (isMailBlockquote(node))
            ++count;
    }
    return count;
}

void updatePositionForNodeRemoval(Position& position, Node& node)
{
    if (position.isNull())
        return;
    switch (position.anchorType()) {
    case Position::PositionIsBeforeChildren:
        if (node.containsIncludingShadowDOM(position.containerNode()))
            position = positionInParentBeforeNode(&node);
        break;
    case Position::PositionIsAfterChildren:
        if (node.containsIncludingShadowDOM(position.containerNode()))
            position = positionInParentBeforeNode(&node);
        break;
    case Position::PositionIsOffsetInAnchor:
        if (position.containerNode() == node.parentNode() && static_cast<unsigned>(position.offsetInContainerNode()) > node.computeNodeIndex())
            position.moveToOffset(position.offsetInContainerNode() - 1);
        else if (node.containsIncludingShadowDOM(position.containerNode()))
            position = positionInParentBeforeNode(&node);
        break;
    case Position::PositionIsAfterAnchor:
        if (node.containsIncludingShadowDOM(position.anchorNode()))
            position = positionInParentAfterNode(&node);
        break;
    case Position::PositionIsBeforeAnchor:
        if (node.containsIncludingShadowDOM(position.anchorNode()))
            position = positionInParentBeforeNode(&node);
        break;
    }
}

bool isMailBlockquote(const Node* node)
{
    ASSERT(node);
    if (!node->hasTagName(blockquoteTag))
        return false;
    return downcast<HTMLElement>(*node).attributeWithoutSynchronization(typeAttr) == "cite";
}

int caretMinOffset(const Node& node)
{
    auto* renderer = node.renderer();
    ASSERT(!node.isCharacterDataNode() || !renderer || renderer->isText());
    return renderer ? renderer->caretMinOffset() : 0;
}

// If a node can contain candidates for VisiblePositions, return the offset of the last candidate, otherwise 
// return the number of children for container nodes and the length for unrendered text nodes.
int caretMaxOffset(const Node& node)
{
    // For rendered text nodes, return the last position that a caret could occupy.
    if (is<Text>(node)) {
        if (auto* renderer = downcast<Text>(node).renderer())
            return renderer->caretMaxOffset();
    }
    return lastOffsetForEditing(node);
}

bool lineBreakExistsAtVisiblePosition(const VisiblePosition& position)
{
    return lineBreakExistsAtPosition(position.deepEquivalent().downstream());
}

bool lineBreakExistsAtPosition(const Position& position)
{
    if (position.isNull())
        return false;

    if (position.anchorNode()->hasTagName(brTag) && position.atFirstEditingPositionForNode())
        return true;

    if (!position.anchorNode()->renderer())
        return false;

    if (!is<Text>(*position.anchorNode()) || !position.anchorNode()->renderer()->style().preserveNewline())
        return false;
    
    Text& textNode = downcast<Text>(*position.anchorNode());
    unsigned offset = position.offsetInContainerNode();
    return offset < textNode.length() && textNode.data()[offset] == '\n';
}

// Modifies selections that have an end point at the edge of a table
// that contains the other endpoint so that they don't confuse
// code that iterates over selected paragraphs.
VisibleSelection selectionForParagraphIteration(const VisibleSelection& original)
{
    VisibleSelection newSelection(original);
    VisiblePosition startOfSelection(newSelection.visibleStart());
    VisiblePosition endOfSelection(newSelection.visibleEnd());
    
    // If the end of the selection to modify is just after a table, and
    // if the start of the selection is inside that table, then the last paragraph
    // that we'll want modify is the last one inside the table, not the table itself
    // (a table is itself a paragraph).
    if (auto* table = isFirstPositionAfterTable(endOfSelection)) {
        if (startOfSelection.deepEquivalent().deprecatedNode()->isDescendantOf(*table))
            newSelection = VisibleSelection(startOfSelection, endOfSelection.previous(CannotCrossEditingBoundary));
    }
    
    // If the start of the selection to modify is just before a table,
    // and if the end of the selection is inside that table, then the first paragraph
    // we'll want to modify is the first one inside the table, not the paragraph
    // containing the table itself.
    if (auto* table = isLastPositionBeforeTable(startOfSelection)) {
        if (endOfSelection.deepEquivalent().deprecatedNode()->isDescendantOf(*table))
            newSelection = VisibleSelection(startOfSelection.next(CannotCrossEditingBoundary), endOfSelection);
    }
    
    return newSelection;
}

// FIXME: indexForVisiblePosition and visiblePositionForIndex use TextIterators to convert between 
// VisiblePositions and indices. But TextIterator iteration using TextIteratorEmitsCharactersBetweenAllVisiblePositions 
// does not exactly match VisiblePosition iteration, so using them to preserve a selection during an editing 
// opertion is unreliable. TextIterator's TextIteratorEmitsCharactersBetweenAllVisiblePositions mode needs to be fixed, 
// or these functions need to be changed to iterate using actual VisiblePositions.
// FIXME: Deploy these functions everywhere that TextIterators are used to convert between VisiblePositions and indices.
int indexForVisiblePosition(const VisiblePosition& visiblePosition, RefPtr<ContainerNode>& scope)
{
    if (visiblePosition.isNull())
        return 0;

    auto position = visiblePosition.deepEquivalent();
    auto& document = *position.document();

    auto* editableRoot = highestEditableRoot(position, AXObjectCache::accessibilityEnabled() ? HasEditableAXRole : ContentIsEditable);
    if (editableRoot && !document.inDesignMode())
        scope = editableRoot;
    else {
        if (position.containerNode()->isInShadowTree())
            scope = position.containerNode()->containingShadowRoot();
        else
            scope = &document;
    }

    auto start = makeBoundaryPoint(firstPositionInNode(scope.get()));
    auto end = makeBoundaryPoint(position.parentAnchoredEquivalent());
    if (!start || !end)
        return 0;

    return characterCount({ *start, *end }, TextIteratorEmitsCharactersBetweenAllVisiblePositions);
}

// FIXME: Merge this function with the one above.
int indexForVisiblePosition(Node& node, const VisiblePosition& visiblePosition, bool forSelectionPreservation)
{
    auto start = makeBoundaryPoint(firstPositionInNode(&node));
    auto end = makeBoundaryPoint(visiblePosition.deepEquivalent().parentAnchoredEquivalent());
    if (!start || !end)
        return 0;

    return characterCount({ *start, *end }, forSelectionPreservation ? TextIteratorEmitsCharactersBetweenAllVisiblePositions : TextIteratorDefaultBehavior);
}

VisiblePosition visiblePositionForPositionWithOffset(const VisiblePosition& position, int offset)
{
    RefPtr<ContainerNode> root;
    unsigned startIndex = indexForVisiblePosition(position, root);
    if (!root)
        return { };

    return visiblePositionForIndex(startIndex + offset, root.get());
}

VisiblePosition visiblePositionForIndex(int index, ContainerNode* scope)
{
    if (!scope)
        return { };
    return { createLegacyEditingPosition(resolveCharacterLocation(makeRangeSelectingNodeContents(*scope), index, TextIteratorEmitsCharactersBetweenAllVisiblePositions)) };
}

VisiblePosition visiblePositionForIndexUsingCharacterIterator(Node& node, int index)
{
    if (index <= 0)
        return { firstPositionInOrBeforeNode(&node), DOWNSTREAM };

    auto range = Range::create(node.document());
    range->selectNodeContents(node);
    CharacterIterator it(range.get());
    it.advance(index - 1);

    if (!it.atEnd() && it.text().length() == 1 && it.text()[0] == '\n') {
        // FIXME: workaround for collapsed range (where only start position is correct) emitted for some emitted newlines.
        it.advance(1);
        if (!it.atEnd())
            return VisiblePosition(createLegacyEditingPosition(it.range().start));
    }

    return { it.atEnd() ? range->endPosition() : createLegacyEditingPosition(it.range().end), UPSTREAM };
}

// Determines whether two positions are visibly next to each other (first then second)
// while ignoring whitespaces and unrendered nodes
static bool isVisiblyAdjacent(const Position& first, const Position& second)
{
    return VisiblePosition(first) == VisiblePosition(second.upstream());
}

// Determines whether a node is inside a range or visibly starts and ends at the boundaries of the range.
// Call this function to determine whether a node is visibly fit inside selectedRange
bool isNodeVisiblyContainedWithin(Node& node, const Range& range)
{
    // If the node is inside the range, then it surely is contained within.
    auto comparisonResult = range.compareNode(node);
    if (!comparisonResult.hasException() && comparisonResult.releaseReturnValue() == Range::NODE_INSIDE)
        return true;

    bool startIsVisuallySame = visiblePositionBeforeNode(node) == range.startPosition();
    if (startIsVisuallySame && comparePositions(positionInParentAfterNode(&node), range.endPosition()) < 0)
        return true;

    bool endIsVisuallySame = visiblePositionAfterNode(node) == range.endPosition();
    if (endIsVisuallySame && comparePositions(range.startPosition(), positionInParentBeforeNode(&node)) < 0)
        return true;

    return startIsVisuallySame && endIsVisuallySame;
}

bool isRenderedAsNonInlineTableImageOrHR(const Node* node)
{
    if (!node)
        return false;
    RenderObject* renderer = node->renderer();
    return renderer && ((renderer->isTable() && !renderer->isInline()) || (renderer->isImage() && !renderer->isInline()) || renderer->isHR());
}

bool areIdenticalElements(const Node& first, const Node& second)
{
    if (!is<Element>(first) || !is<Element>(second))
        return false;
    auto& firstElement = downcast<Element>(first);
    auto& secondElement = downcast<Element>(second);
    return firstElement.hasTagName(secondElement.tagQName()) && firstElement.hasEquivalentAttributes(secondElement);
}

bool isNonTableCellHTMLBlockElement(const Node* node)
{
    return node->hasTagName(listingTag)
        || node->hasTagName(olTag)
        || node->hasTagName(preTag)
        || is<HTMLTableElement>(*node)
        || node->hasTagName(ulTag)
        || node->hasTagName(xmpTag)
        || node->hasTagName(h1Tag)
        || node->hasTagName(h2Tag)
        || node->hasTagName(h3Tag)
        || node->hasTagName(h4Tag)
        || node->hasTagName(h5Tag);
}

Position adjustedSelectionStartForStyleComputation(const VisibleSelection& selection)
{
    // This function is used by range style computations to avoid bugs like:
    // <rdar://problem/4017641> REGRESSION (Mail): you can only bold/unbold a selection starting from end of line once
    // It is important to skip certain irrelevant content at the start of the selection, so we do not wind up 
    // with a spurious "mixed" style.

    auto visiblePosition = selection.visibleStart();
    if (visiblePosition.isNull())
        return { };

    // if the selection is a caret, just return the position, since the style
    // behind us is relevant
    if (selection.isCaret())
        return visiblePosition.deepEquivalent();

    // if the selection starts just before a paragraph break, skip over it
    if (isEndOfParagraph(visiblePosition))
        return visiblePosition.next().deepEquivalent().downstream();

    // otherwise, make sure to be at the start of the first selected node,
    // instead of possibly at the end of the last node before the selection
    return visiblePosition.deepEquivalent().downstream();
}

// FIXME: Should this be deprecated like deprecatedEnclosingBlockFlowElement is?
bool isBlockFlowElement(const Node& node)
{
    if (!node.isElementNode())
        return false;
    auto* renderer = downcast<Element>(node).renderer();
    return renderer && renderer->isRenderBlockFlow();
}

Element* deprecatedEnclosingBlockFlowElement(Node* node)
{
    if (!node)
        return nullptr;
    if (isBlockFlowElement(*node))
        return downcast<Element>(node);
    while ((node = node->parentNode())) {
        if (isBlockFlowElement(*node) || is<HTMLBodyElement>(*node))
            return downcast<Element>(node);
    }
    return nullptr;
}

static inline bool caretRendersInsideNode(Node& node)
{
    return !isRenderedTable(&node) && !editingIgnoresContent(node);
}

RenderBlock* rendererForCaretPainting(Node* node)
{
    if (!node)
        return nullptr;

    auto* renderer = node->renderer();
    if (!renderer)
        return nullptr;

    // If caretNode is a block and caret is inside it, then caret should be painted by that block.
    bool paintedByBlock = is<RenderBlockFlow>(*renderer) && caretRendersInsideNode(*node);
    return paintedByBlock ? downcast<RenderBlock>(renderer) : renderer->containingBlock();
}

LayoutRect localCaretRectInRendererForCaretPainting(const VisiblePosition& caretPosition, RenderBlock*& caretPainter)
{
    if (caretPosition.isNull())
        return LayoutRect();

    ASSERT(caretPosition.deepEquivalent().deprecatedNode()->renderer());

    // First compute a rect local to the renderer at the selection start.
    RenderObject* renderer;
    LayoutRect localRect = caretPosition.localCaretRect(renderer);

    return localCaretRectInRendererForRect(localRect, caretPosition.deepEquivalent().deprecatedNode(), renderer, caretPainter);
}

LayoutRect localCaretRectInRendererForRect(LayoutRect& localRect, Node* node, RenderObject* renderer, RenderBlock*& caretPainter)
{
    // Get the renderer that will be responsible for painting the caret
    // (which is either the renderer we just found, or one of its containers).
    caretPainter = rendererForCaretPainting(node);

    // Compute an offset between the renderer and the caretPainter.
    while (renderer != caretPainter) {
        RenderElement* containerObject = renderer->container();
        if (!containerObject)
            return LayoutRect();
        localRect.move(renderer->offsetFromContainer(*containerObject, localRect.location()));
        renderer = containerObject;
    }

    return localRect;
}

IntRect absoluteBoundsForLocalCaretRect(RenderBlock* rendererForCaretPainting, const LayoutRect& rect, bool* insideFixed)
{
    if (insideFixed)
        *insideFixed = false;

    if (!rendererForCaretPainting || rect.isEmpty())
        return IntRect();

    LayoutRect localRect(rect);
    rendererForCaretPainting->flipForWritingMode(localRect);
    return rendererForCaretPainting->localToAbsoluteQuad(FloatRect(localRect), UseTransforms, insideFixed).enclosingBoundingBox();
}

HashSet<RefPtr<HTMLImageElement>> visibleImageElementsInRangeWithNonLoadedImages(const Range& range)
{
    HashSet<RefPtr<HTMLImageElement>> result;
    for (TextIterator iterator(range); !iterator.atEnd(); iterator.advance()) {
        if (!is<HTMLImageElement>(iterator.node()))
            continue;

        auto& imageElement = downcast<HTMLImageElement>(*iterator.node());
        auto* cachedImage = imageElement.cachedImage();
        if (cachedImage && cachedImage->isLoading())
            result.add(&imageElement);
    }
    return result;
}

} // namespace WebCore
