/*
 * Copyright (C) 2007, 2009, 2016 Apple Inc. All rights reserved.
 * Copyright (C) 2012 Google 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. 
 * 3.  Neither the name of Apple Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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 "DOMSelection.h"

#include "Document.h"
#include "Editing.h"
#include "Frame.h"
#include "FrameSelection.h"
#include "Range.h"
#include "TextIterator.h"

namespace WebCore {

static Node* selectionShadowAncestor(Frame& frame)
{
    auto* node = frame.selection().selection().base().anchorNode();
    if (!node)
        return nullptr;
    if (!node->isInShadowTree())
        return nullptr;
    // FIXME: Unclear on why this needs to be the possibly null frame.document() instead of the never null node->document().
    return frame.document()->ancestorNodeInThisScope(node);
}

DOMSelection::DOMSelection(Frame& frame)
    : DOMWindowProperty(&frame)
{
}

const VisibleSelection& DOMSelection::visibleSelection() const
{
    ASSERT(m_frame);
    return m_frame->selection().selection();
}

static Position anchorPosition(const VisibleSelection& selection)
{
    auto anchor = selection.isBaseFirst() ? selection.start() : selection.end();
    return anchor.parentAnchoredEquivalent();
}

static Position focusPosition(const VisibleSelection& selection)
{
    auto focus = selection.isBaseFirst() ? selection.end() : selection.start();
    return focus.parentAnchoredEquivalent();
}

static Position basePosition(const VisibleSelection& selection)
{
    return selection.base().parentAnchoredEquivalent();
}

static Position extentPosition(const VisibleSelection& selection)
{
    return selection.extent().parentAnchoredEquivalent();
}

Node* DOMSelection::anchorNode() const
{
    if (!m_frame)
        return 0;
    return shadowAdjustedNode(anchorPosition(visibleSelection()));
}

unsigned DOMSelection::anchorOffset() const
{
    if (!m_frame)
        return 0;
    return shadowAdjustedOffset(anchorPosition(visibleSelection()));
}

Node* DOMSelection::focusNode() const
{
    if (!m_frame)
        return nullptr;
    return shadowAdjustedNode(focusPosition(visibleSelection()));
}

unsigned DOMSelection::focusOffset() const
{
    if (!m_frame)
        return 0;
    return shadowAdjustedOffset(focusPosition(visibleSelection()));
}

Node* DOMSelection::baseNode() const
{
    if (!m_frame)
        return 0;
    return shadowAdjustedNode(basePosition(visibleSelection()));
}

unsigned DOMSelection::baseOffset() const
{
    if (!m_frame)
        return 0;
    return shadowAdjustedOffset(basePosition(visibleSelection()));
}

Node* DOMSelection::extentNode() const
{
    if (!m_frame)
        return 0;
    return shadowAdjustedNode(extentPosition(visibleSelection()));
}

unsigned DOMSelection::extentOffset() const
{
    if (!m_frame)
        return 0;
    return shadowAdjustedOffset(extentPosition(visibleSelection()));
}

bool DOMSelection::isCollapsed() const
{
    if (!m_frame || selectionShadowAncestor(*m_frame))
        return true;
    return !m_frame->selection().isRange();
}

String DOMSelection::type() const
{
    if (!m_frame)
        return ASCIILiteral("None");
    auto& selection = m_frame->selection();
    if (selection.isNone())
        return ASCIILiteral("None");
    if (selection.isCaret())
        return ASCIILiteral("Caret");
    return ASCIILiteral("Range");
}

unsigned DOMSelection::rangeCount() const
{
    return !m_frame || m_frame->selection().isNone() ? 0 : 1;
}

void DOMSelection::collapse(Node* node, unsigned offset)
{
    if (!isValidForPosition(node))
        return;

    Ref<Frame> protector(*m_frame);
    m_frame->selection().moveTo(createLegacyEditingPosition(node, offset), DOWNSTREAM);
}

ExceptionOr<void> DOMSelection::collapseToEnd()
{
    if (!m_frame)
        return { };
    auto& selection = m_frame->selection();
    if (selection.isNone())
        return Exception { InvalidStateError };

    Ref<Frame> protector(*m_frame);
    selection.moveTo(selection.selection().end(), DOWNSTREAM);
    return { };
}

ExceptionOr<void> DOMSelection::collapseToStart()
{
    if (!m_frame)
        return { };
    auto& selection = m_frame->selection();
    if (selection.isNone())
        return Exception { InvalidStateError };

    Ref<Frame> protector(*m_frame);
    selection.moveTo(selection.selection().start(), DOWNSTREAM);
    return { };
}

void DOMSelection::empty()
{
    if (!m_frame)
        return;
    m_frame->selection().clear();
}

void DOMSelection::setBaseAndExtent(Node* baseNode, unsigned baseOffset, Node* extentNode, unsigned extentOffset)
{
    if (!isValidForPosition(baseNode) || !isValidForPosition(extentNode))
        return;

    Ref<Frame> protector(*m_frame);
    m_frame->selection().moveTo(createLegacyEditingPosition(baseNode, baseOffset), createLegacyEditingPosition(extentNode, extentOffset), DOWNSTREAM);
}

void DOMSelection::setPosition(Node* node, unsigned offset)
{
    if (!isValidForPosition(node))
        return;

    Ref<Frame> protector(*m_frame);
    m_frame->selection().moveTo(createLegacyEditingPosition(node, offset), DOWNSTREAM);
}

void DOMSelection::modify(const String& alterString, const String& directionString, const String& granularityString)
{
    if (!m_frame)
        return;

    FrameSelection::EAlteration alter;
    if (equalLettersIgnoringASCIICase(alterString, "extend"))
        alter = FrameSelection::AlterationExtend;
    else if (equalLettersIgnoringASCIICase(alterString, "move"))
        alter = FrameSelection::AlterationMove;
    else
        return;

    SelectionDirection direction;
    if (equalLettersIgnoringASCIICase(directionString, "forward"))
        direction = DirectionForward;
    else if (equalLettersIgnoringASCIICase(directionString, "backward"))
        direction = DirectionBackward;
    else if (equalLettersIgnoringASCIICase(directionString, "left"))
        direction = DirectionLeft;
    else if (equalLettersIgnoringASCIICase(directionString, "right"))
        direction = DirectionRight;
    else
        return;

    TextGranularity granularity;
    if (equalLettersIgnoringASCIICase(granularityString, "character"))
        granularity = CharacterGranularity;
    else if (equalLettersIgnoringASCIICase(granularityString, "word"))
        granularity = WordGranularity;
    else if (equalLettersIgnoringASCIICase(granularityString, "sentence"))
        granularity = SentenceGranularity;
    else if (equalLettersIgnoringASCIICase(granularityString, "line"))
        granularity = LineGranularity;
    else if (equalLettersIgnoringASCIICase(granularityString, "paragraph"))
        granularity = ParagraphGranularity;
    else if (equalLettersIgnoringASCIICase(granularityString, "lineboundary"))
        granularity = LineBoundary;
    else if (equalLettersIgnoringASCIICase(granularityString, "sentenceboundary"))
        granularity = SentenceBoundary;
    else if (equalLettersIgnoringASCIICase(granularityString, "paragraphboundary"))
        granularity = ParagraphBoundary;
    else if (equalLettersIgnoringASCIICase(granularityString, "documentboundary"))
        granularity = DocumentBoundary;
    else
        return;

    Ref<Frame> protector(*m_frame);
    m_frame->selection().modify(alter, direction, granularity);
}

ExceptionOr<void> DOMSelection::extend(Node& node, unsigned offset)
{
    if (!m_frame)
        return { };
    if (offset > (node.offsetInCharacters() ? caretMaxOffset(node) : node.countChildNodes()))
        return Exception { IndexSizeError };
    if (!isValidForPosition(&node))
        return { };

    Ref<Frame> protector(*m_frame);
    m_frame->selection().setExtent(createLegacyEditingPosition(&node, offset), DOWNSTREAM);
    return { };
}

ExceptionOr<Ref<Range>> DOMSelection::getRangeAt(unsigned index)
{
    if (index >= rangeCount())
        return Exception { IndexSizeError };

    // If you're hitting this, you've added broken multi-range selection support.
    ASSERT(rangeCount() == 1);

    if (auto* shadowAncestor = selectionShadowAncestor(*m_frame)) {
        auto* container = shadowAncestor->parentNodeGuaranteedHostFree();
        unsigned offset = shadowAncestor->computeNodeIndex();
        return Range::create(shadowAncestor->document(), container, offset, container, offset);
    }

    auto firstRange = m_frame->selection().selection().firstRange();
    ASSERT(firstRange);
    if (!firstRange)
        return Exception { IndexSizeError };
    return firstRange.releaseNonNull();
}

void DOMSelection::removeAllRanges()
{
    if (!m_frame)
        return;
    m_frame->selection().clear();
}

void DOMSelection::addRange(Range& range)
{
    if (!m_frame)
        return;

    Ref<Frame> protector(*m_frame);

    auto& selection = m_frame->selection();
    if (selection.isNone()) {
        selection.moveTo(&range);
        return;
    }

    auto normalizedRange = selection.selection().toNormalizedRange();
    if (!normalizedRange)
        return;

    auto result = range.compareBoundaryPoints(Range::START_TO_START, *normalizedRange);
    if (!result.hasException() && result.releaseReturnValue() == -1) {
        // We don't support discontiguous selection. We don't do anything if the two ranges don't intersect.
        result = range.compareBoundaryPoints(Range::START_TO_END, *normalizedRange);
        if (!result.hasException() && result.releaseReturnValue() > -1) {
            result = range.compareBoundaryPoints(Range::END_TO_END, *normalizedRange);
            if (!result.hasException() && result.releaseReturnValue() == -1) {
                // The ranges intersect.
                selection.moveTo(range.startPosition(), normalizedRange->endPosition(), DOWNSTREAM);
            } else {
                // The new range contains the original range.
                selection.moveTo(&range);
            }
        }
    } else {
        // We don't support discontiguous selection. We don't do anything if the two ranges don't intersect.
        result = range.compareBoundaryPoints(Range::END_TO_START, *normalizedRange);
        if (!result.hasException() && result.releaseReturnValue() < 1) {
            result = range.compareBoundaryPoints(Range::END_TO_END, *normalizedRange);
            if (!result.hasException() && result.releaseReturnValue() == -1) {
                // The original range contains the new range.
                selection.moveTo(normalizedRange.get());
            } else {
                // The ranges intersect.
                selection.moveTo(normalizedRange->startPosition(), range.endPosition(), DOWNSTREAM);
            }
        }
    }
}

void DOMSelection::deleteFromDocument()
{
    if (!m_frame)
        return;

    auto& selection = m_frame->selection();
    if (selection.isNone())
        return;

    auto selectedRange = selection.selection().toNormalizedRange();
    if (!selectedRange || selectedRange->shadowRoot())
        return;

    Ref<Frame> protector(*m_frame);
    selectedRange->deleteContents();
    setBaseAndExtent(&selectedRange->startContainer(), selectedRange->startOffset(), &selectedRange->startContainer(), selectedRange->startOffset());
}

bool DOMSelection::containsNode(Node& node, bool allowPartial) const
{
    if (!m_frame)
        return false;

    auto& selection = m_frame->selection();
    if (m_frame->document() != &node.document() || selection.isNone())
        return false;

    Ref<Node> protectedNode(node);
    auto selectedRange = selection.selection().toNormalizedRange();
    if (!selectedRange)
        return false;

    ContainerNode* parentNode = node.parentNode();
    if (!parentNode || !parentNode->isConnected())
        return false;
    unsigned nodeIndex = node.computeNodeIndex();

    auto startsResult = Range::compareBoundaryPoints(parentNode, nodeIndex, &selectedRange->startContainer(), selectedRange->startOffset());
    ASSERT(!startsResult.hasException());
    auto endsResult = Range::compareBoundaryPoints(parentNode, nodeIndex + 1, &selectedRange->endContainer(), selectedRange->endOffset());
    ASSERT(!endsResult.hasException());
    bool isNodeFullySelected = !startsResult.hasException() && startsResult.releaseReturnValue() >= 0
        && !endsResult.hasException() && endsResult.releaseReturnValue() <= 0;
    if (isNodeFullySelected)
        return true;

    auto startEndResult = Range::compareBoundaryPoints(parentNode, nodeIndex, &selectedRange->endContainer(), selectedRange->endOffset());
    ASSERT(!startEndResult.hasException());
    auto endStartResult = Range::compareBoundaryPoints(parentNode, nodeIndex + 1, &selectedRange->startContainer(), selectedRange->startOffset());
    ASSERT(!endStartResult.hasException());
    bool isNodeFullyUnselected = (!startEndResult.hasException() && startEndResult.releaseReturnValue() > 0)
        || (!endStartResult.hasException() && endStartResult.releaseReturnValue() < 0);
    if (isNodeFullyUnselected)
        return false;

    return allowPartial || node.isTextNode();
}

void DOMSelection::selectAllChildren(Node& node)
{
    // This doesn't (and shouldn't) select text node characters.
    setBaseAndExtent(&node, 0, &node, node.countChildNodes());
}

String DOMSelection::toString()
{
    if (!m_frame)
        return String();
    return plainText(m_frame->selection().selection().toNormalizedRange().get());
}

Node* DOMSelection::shadowAdjustedNode(const Position& position) const
{
    if (position.isNull())
        return nullptr;

    auto* containerNode = position.containerNode();
    auto* adjustedNode = m_frame->document()->ancestorNodeInThisScope(containerNode);
    if (!adjustedNode)
        return nullptr;

    if (containerNode == adjustedNode)
        return containerNode;

    return adjustedNode->parentNodeGuaranteedHostFree();
}

unsigned DOMSelection::shadowAdjustedOffset(const Position& position) const
{
    if (position.isNull())
        return 0;

    auto* containerNode = position.containerNode();
    auto* adjustedNode = m_frame->document()->ancestorNodeInThisScope(containerNode);
    if (!adjustedNode)
        return 0;

    if (containerNode == adjustedNode)
        return position.computeOffsetInContainerNode();

    return adjustedNode->computeNodeIndex();
}

bool DOMSelection::isValidForPosition(Node* node) const
{
    if (!m_frame)
        return false;
    if (!node)
        return true;
    return &node->document() == m_frame->document();
}

} // namespace WebCore
