/*
 * Copyright (C) 2006, 2010 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 "InsertListCommand.h"

#include "Editing.h"
#include "ElementTraversal.h"
#include "HTMLBRElement.h"
#include "HTMLLIElement.h"
#include "HTMLNames.h"
#include "HTMLUListElement.h"
#include "Range.h"
#include "VisibleUnits.h"

namespace WebCore {

using namespace HTMLNames;

static Node* enclosingListChild(Node* node, Node* listNode)
{
    Node* listChild = enclosingListChild(node);
    while (listChild && enclosingList(listChild) != listNode)
        listChild = enclosingListChild(listChild->parentNode());
    return listChild;
}

RefPtr<HTMLElement> InsertListCommand::insertList(Document& document, Type type)
{
    RefPtr<InsertListCommand> insertCommand = create(document, type);
    insertCommand->apply();
    return insertCommand->m_listElement;
}

HTMLElement* InsertListCommand::fixOrphanedListChild(Node& node)
{
    auto listElement = HTMLUListElement::create(document());
    insertNodeBefore(listElement.copyRef(), node);
    if (!listElement->hasEditableStyle())
        return nullptr;

    removeNode(node);
    appendNode(node, listElement.copyRef());
    m_listElement = WTFMove(listElement);
    return m_listElement.get();
}

Ref<HTMLElement> InsertListCommand::mergeWithNeighboringLists(HTMLElement& list)
{
    Ref<HTMLElement> protectedList = list;
    Element* previousList = list.previousElementSibling();
    if (canMergeLists(previousList, &list))
        mergeIdenticalElements(*previousList, list);

    Element* sibling = ElementTraversal::nextSibling(list);
    if (!is<HTMLElement>(sibling))
        return protectedList;

    Ref<HTMLElement> nextList = downcast<HTMLElement>(*sibling);
    if (canMergeLists(&list, nextList.ptr())) {
        mergeIdenticalElements(list, nextList);
        return nextList;
    }
    return protectedList;
}

bool InsertListCommand::selectionHasListOfType(const VisibleSelection& selection, const QualifiedName& listTag)
{
    VisiblePosition start = selection.visibleStart();

    if (!enclosingList(start.deepEquivalent().deprecatedNode()))
        return false;

    VisiblePosition end = startOfParagraph(selection.visibleEnd());
    while (start.isNotNull() && start != end) {
        Element* listNode = enclosingList(start.deepEquivalent().deprecatedNode());
        if (!listNode || !listNode->hasTagName(listTag))
            return false;
        start = startOfNextParagraph(start);
    }

    return true;
}

InsertListCommand::InsertListCommand(Document& document, Type type)
    : CompositeEditCommand(document)
    , m_type(type)
{
}

void InsertListCommand::doApply()
{
    VisiblePosition visibleEnd = endingSelection().visibleEnd();
    VisiblePosition visibleStart = endingSelection().visibleStart();

    if (visibleEnd.isNull() || visibleStart.isNull() || !endingSelection().isContentRichlyEditable())
        return;

    // When a selection ends at the start of a paragraph, we rarely paint
    // the selection gap before that paragraph, because there often is no gap.  
    // In a case like this, it's not obvious to the user that the selection 
    // ends "inside" that paragraph, so it would be confusing if InsertUn{Ordered}List 
    // operated on that paragraph.
    // FIXME: We paint the gap before some paragraphs that are indented with left 
    // margin/padding, but not others.  We should make the gap painting more consistent and 
    // then use a left margin/padding rule here.
    if (visibleEnd != visibleStart && isStartOfParagraph(visibleEnd, CanSkipOverEditingBoundary)) {
        setEndingSelection(VisibleSelection(visibleStart, visibleEnd.previous(CannotCrossEditingBoundary), endingSelection().isDirectional()));
        if (!endingSelection().rootEditableElement())
            return;
    }

    auto& listTag = (m_type == Type::OrderedList) ? olTag : ulTag;
    if (endingSelection().isRange()) {
        VisibleSelection selection = selectionForParagraphIteration(endingSelection());
        ASSERT(selection.isRange());
        VisiblePosition startOfSelection = selection.visibleStart();
        VisiblePosition endOfSelection = selection.visibleEnd();
        VisiblePosition startOfLastParagraph = startOfParagraph(endOfSelection, CanSkipOverEditingBoundary);

        if (startOfParagraph(startOfSelection, CanSkipOverEditingBoundary) != startOfLastParagraph) {
            bool forceCreateList = !selectionHasListOfType(selection, listTag);

            RefPtr<Range> currentSelection = endingSelection().firstRange();
            VisiblePosition startOfCurrentParagraph = startOfSelection;
            while (!inSameParagraph(startOfCurrentParagraph, startOfLastParagraph, CanCrossEditingBoundary)) {
                // doApply() may operate on and remove the last paragraph of the selection from the document 
                // if it's in the same list item as startOfCurrentParagraph.  Return early to avoid an 
                // infinite loop and because there is no more work to be done.
                // FIXME(<rdar://problem/5983974>): The endingSelection() may be incorrect here.  Compute 
                // the new location of endOfSelection and use it as the end of the new selection.
                if (!startOfLastParagraph.deepEquivalent().anchorNode()->isConnected())
                    return;
                setEndingSelection(startOfCurrentParagraph);

                // Save and restore endOfSelection and startOfLastParagraph when necessary
                // since moveParagraph and movePragraphWithClones can remove nodes.
                // FIXME: This is an inefficient way to keep selection alive because indexForVisiblePosition walks from
                // the beginning of the document to the endOfSelection everytime this code is executed.
                // But not using index is hard because there are so many ways we can lose selection inside doApplyForSingleParagraph.
                RefPtr<ContainerNode> scope;
                int indexForEndOfSelection = indexForVisiblePosition(endOfSelection, scope);
                doApplyForSingleParagraph(forceCreateList, listTag, currentSelection.get());
                if (endOfSelection.isNull() || endOfSelection.isOrphan() || startOfLastParagraph.isNull() || startOfLastParagraph.isOrphan()) {
                    endOfSelection = visiblePositionForIndex(indexForEndOfSelection, scope.get());
                    // If endOfSelection is null, then some contents have been deleted from the document.
                    // This should never happen and if it did, exit early immediately because we've lost the loop invariant.
                    ASSERT(endOfSelection.isNotNull());
                    if (endOfSelection.isNull())
                        return;
                    startOfLastParagraph = startOfParagraph(endOfSelection, CanSkipOverEditingBoundary);
                }

                // Fetch the start of the selection after moving the first paragraph,
                // because moving the paragraph will invalidate the original start.  
                // We'll use the new start to restore the original selection after 
                // we modified all selected paragraphs.
                if (startOfCurrentParagraph == startOfSelection)
                    startOfSelection = endingSelection().visibleStart();

                startOfCurrentParagraph = startOfNextParagraph(endingSelection().visibleStart());
            }
            setEndingSelection(endOfSelection);
            doApplyForSingleParagraph(forceCreateList, listTag, currentSelection.get());
            // Fetch the end of the selection, for the reason mentioned above.
            endOfSelection = endingSelection().visibleEnd();
            setEndingSelection(VisibleSelection(startOfSelection, endOfSelection, endingSelection().isDirectional()));
            return;
        }
    }

    doApplyForSingleParagraph(false, listTag, endingSelection().firstRange().get());
}

EditAction InsertListCommand::editingAction() const
{
    return m_type == Type::OrderedList ? EditAction::InsertOrderedList : EditAction::InsertUnorderedList;
}

void InsertListCommand::doApplyForSingleParagraph(bool forceCreateList, const HTMLQualifiedName& listTag, Range* currentSelection)
{
    // FIXME: This will produce unexpected results for a selection that starts just before a
    // table and ends inside the first cell, selectionForParagraphIteration should probably
    // be renamed and deployed inside setEndingSelection().
    Node* selectionNode = endingSelection().start().deprecatedNode();
    Node* listChildNode = enclosingListChild(selectionNode);
    bool switchListType = false;
    if (listChildNode) {
        // Remove the list chlild.
        RefPtr<HTMLElement> listNode = enclosingList(listChildNode);
        if (!listNode) {
            RefPtr<HTMLElement> listElement = fixOrphanedListChild(*listChildNode);
            if (!listElement)
                return;

            listNode = mergeWithNeighboringLists(*listElement);
        }
        
        if (!listNode->hasTagName(listTag)) {
            // listChildNode will be removed from the list and a list of type m_type will be created.
            switchListType = true;
        }

        // If the list is of the desired type, and we are not removing the list, then exit early.
        if (!switchListType && forceCreateList)
            return;

        // If the entire list is selected, then convert the whole list.
        if (switchListType && isNodeVisiblyContainedWithin(*listNode, *currentSelection)) {
            bool rangeStartIsInList = visiblePositionBeforeNode(*listNode) == currentSelection->startPosition();
            bool rangeEndIsInList = visiblePositionAfterNode(*listNode) == currentSelection->endPosition();

            RefPtr<HTMLElement> newList = createHTMLElement(document(), listTag);
            insertNodeBefore(*newList, *listNode);
            if (!newList->hasEditableStyle())
                return;

            auto* firstChildInList = enclosingListChild(VisiblePosition(firstPositionInNode(listNode.get())).deepEquivalent().deprecatedNode(), listNode.get());
            Node* outerBlock = firstChildInList && isBlockFlowElement(*firstChildInList) ? firstChildInList : listNode.get();
            
            moveParagraphWithClones(firstPositionInNode(listNode.get()), lastPositionInNode(listNode.get()), newList.get(), outerBlock);

            // Manually remove listNode because moveParagraphWithClones sometimes leaves it behind in the document.
            // See the bug 33668 and editing/execCommand/insert-list-orphaned-item-with-nested-lists.html.
            // FIXME: This might be a bug in moveParagraphWithClones or deleteSelection.
            if (listNode && listNode->isConnected())
                removeNode(*listNode);

            newList = mergeWithNeighboringLists(*newList);

            // Restore the start and the end of current selection if they started inside listNode
            // because moveParagraphWithClones could have removed them.
            if (rangeStartIsInList && newList)
                currentSelection->setStart(*newList, 0);
            if (rangeEndIsInList && newList)
                currentSelection->setEnd(*newList, lastOffsetInNode(newList.get()));

            setEndingSelection(VisiblePosition(firstPositionInNode(newList.get())));

            return;
        }
        
        unlistifyParagraph(endingSelection().visibleStart(), listNode.get(), listChildNode);
    }

    if (!listChildNode || switchListType || forceCreateList)
        m_listElement = listifyParagraph(endingSelection().visibleStart(), listTag);
}

void InsertListCommand::unlistifyParagraph(const VisiblePosition& originalStart, HTMLElement* listNode, Node* listChildNode)
{
    Node* nextListChild;
    Node* previousListChild;
    VisiblePosition start;
    VisiblePosition end;

    if (!listNode->parentNode()->hasEditableStyle())
        return;

    if (listChildNode->hasTagName(liTag)) {
        start = firstPositionInNode(listChildNode);
        end = lastPositionInNode(listChildNode);
        nextListChild = listChildNode->nextSibling();
        previousListChild = listChildNode->previousSibling();
    } else {
        // A paragraph is visually a list item minus a list marker.  The paragraph will be moved.
        start = startOfParagraph(originalStart, CanSkipOverEditingBoundary);
        end = endOfParagraph(start, CanSkipOverEditingBoundary);
        nextListChild = enclosingListChild(end.next().deepEquivalent().deprecatedNode(), listNode);
        ASSERT(nextListChild != listChildNode);
        previousListChild = enclosingListChild(start.previous().deepEquivalent().deprecatedNode(), listNode);
        ASSERT(previousListChild != listChildNode);
    }
    // When removing a list, we must always create a placeholder to act as a point of insertion
    // for the list content being removed.
    auto placeholder = HTMLBRElement::create(document());
    RefPtr<Element> nodeToInsert = placeholder.copyRef();
    // If the content of the list item will be moved into another list, put it in a list item
    // so that we don't create an orphaned list child.
    if (enclosingList(listNode)) {
        nodeToInsert = HTMLLIElement::create(document());
        appendNode(placeholder.copyRef(), *nodeToInsert);
    }

    if (nextListChild && previousListChild) {
        // We want to pull listChildNode out of listNode, and place it before nextListChild 
        // and after previousListChild, so we split listNode and insert it between the two lists.  
        // But to split listNode, we must first split ancestors of listChildNode between it and listNode,
        // if any exist.
        // FIXME: We appear to split at nextListChild as opposed to listChildNode so that when we remove
        // listChildNode below in moveParagraphs, previousListChild will be removed along with it if it is 
        // unrendered. But we ought to remove nextListChild too, if it is unrendered.
        splitElement(*listNode, *splitTreeToNode(*nextListChild, *listNode));
        insertNodeBefore(nodeToInsert.releaseNonNull(), *listNode);
    } else if (nextListChild || listChildNode->parentNode() != listNode) {
        // Just because listChildNode has no previousListChild doesn't mean there isn't any content
        // in listNode that comes before listChildNode, as listChildNode could have ancestors
        // between it and listNode. So, we split up to listNode before inserting the placeholder
        // where we're about to move listChildNode to.
        if (listChildNode->parentNode() != listNode)
            splitElement(*listNode, *splitTreeToNode(*listChildNode, *listNode).get());
        insertNodeBefore(nodeToInsert.releaseNonNull(), *listNode);
    } else
        insertNodeAfter(nodeToInsert.releaseNonNull(), *listNode);

    VisiblePosition insertionPoint = VisiblePosition(positionBeforeNode(placeholder.ptr()));
    moveParagraphs(start, end, insertionPoint, true);
}

static Element* adjacentEnclosingList(const VisiblePosition& pos, const VisiblePosition& adjacentPos, const QualifiedName& listTag)
{
    Element* listNode = outermostEnclosingList(adjacentPos.deepEquivalent().deprecatedNode());

    if (!listNode)
        return 0;

    Node* previousCell = enclosingTableCell(pos.deepEquivalent());
    Node* currentCell = enclosingTableCell(adjacentPos.deepEquivalent());

    if (!listNode->hasTagName(listTag)
        || listNode->contains(pos.deepEquivalent().deprecatedNode())
        || previousCell != currentCell
        || enclosingList(listNode) != enclosingList(pos.deepEquivalent().deprecatedNode()))
        return 0;

    return listNode;
}

RefPtr<HTMLElement> InsertListCommand::listifyParagraph(const VisiblePosition& originalStart, const QualifiedName& listTag)
{
    VisiblePosition start = startOfParagraph(originalStart, CanSkipOverEditingBoundary);
    VisiblePosition end = endOfParagraph(start, CanSkipOverEditingBoundary);
    
    if (start.isNull() || end.isNull() || !start.deepEquivalent().containerNode()->hasEditableStyle() || !end.deepEquivalent().containerNode()->hasEditableStyle())
        return 0;

    // Check for adjoining lists.
    auto listItemElement = HTMLLIElement::create(document());
    auto placeholder = HTMLBRElement::create(document());
    appendNode(placeholder.copyRef(), listItemElement.copyRef());

    // Place list item into adjoining lists.
    Element* previousList = adjacentEnclosingList(start.deepEquivalent(), start.previous(CannotCrossEditingBoundary), listTag);
    Element* nextList = adjacentEnclosingList(start.deepEquivalent(), end.next(CannotCrossEditingBoundary), listTag);
    RefPtr<HTMLElement> listElement;
    if (previousList)
        appendNode(WTFMove(listItemElement), *previousList);
    else if (nextList)
        insertNodeAt(WTFMove(listItemElement), positionBeforeNode(nextList));
    else {
        // Create the list.
        listElement = createHTMLElement(document(), listTag);
        appendNode(WTFMove(listItemElement), *listElement);

        if (start == end && isBlock(start.deepEquivalent().deprecatedNode())) {
            // Inserting the list into an empty paragraph that isn't held open 
            // by a br or a '\n', will invalidate start and end.  Insert 
            // a placeholder and then recompute start and end.
            auto blockPlaceholder = insertBlockPlaceholder(start.deepEquivalent());
            start = positionBeforeNode(blockPlaceholder.get());
            end = start;
        }

        // Insert the list at a position visually equivalent to start of the
        // paragraph that is being moved into the list. 
        // Try to avoid inserting it somewhere where it will be surrounded by 
        // inline ancestors of start, since it is easier for editing to produce 
        // clean markup when inline elements are pushed down as far as possible.
        Position insertionPos(start.deepEquivalent().upstream());
        // Also avoid the containing list item.
        Node* listChild = enclosingListChild(insertionPos.deprecatedNode());
        if (listChild && listChild->hasTagName(liTag))
            insertionPos = positionInParentBeforeNode(listChild);

        if (!isEditablePosition(insertionPos))
            return 0;

        insertNodeAt(*listElement, insertionPos);

        // We inserted the list at the start of the content we're about to move
        // Update the start of content, so we don't try to move the list into itself.  bug 19066
        // Layout is necessary since start's node's inline renderers may have been destroyed by the insertion
        // The end of the content may have changed after the insertion and layout so update it as well.
        if (insertionPos == start.deepEquivalent()) {
            listElement->document().updateLayoutIgnorePendingStylesheets();
            start = startOfParagraph(originalStart, CanSkipOverEditingBoundary);
            end = endOfParagraph(start, CanSkipOverEditingBoundary);
        }
    }

    moveParagraph(start, end, positionBeforeNode(placeholder.ptr()), true);

    if (listElement)
        return mergeWithNeighboringLists(*listElement);

    if (canMergeLists(previousList, nextList))
        mergeIdenticalElements(*previousList, *nextList);

    return listElement;
}

}
