/*
 * Copyright (C) 2020 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. 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 INC. 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 "SimpleRange.h"

#include "CharacterData.h"
#include "Frame.h"
#include "HTMLFrameOwnerElement.h"
#include "NodeTraversal.h"
#include "ShadowRoot.h"

namespace WebCore {

SimpleRange::SimpleRange(const BoundaryPoint& start, const BoundaryPoint& end)
    : start(start)
    , end(end)
{
}

SimpleRange::SimpleRange(BoundaryPoint&& start, BoundaryPoint&& end)
    : start(WTFMove(start))
    , end(WTFMove(end))
{
}

bool operator==(const SimpleRange& a, const SimpleRange& b)
{
    return a.start == b.start && a.end == b.end;
}

std::optional<SimpleRange> makeRangeSelectingNode(Node& node)
{
    auto parent = node.parentNode();
    if (!parent)
        return std::nullopt;
    unsigned offset = node.computeNodeIndex();
    return SimpleRange { { *parent, offset }, { *parent, offset + 1 } };
}

SimpleRange makeRangeSelectingNodeContents(Node& node)
{
    return { makeBoundaryPointBeforeNodeContents(node), makeBoundaryPointAfterNodeContents(node) };
}

OffsetRange characterDataOffsetRange(const SimpleRange& range, const Node& node)
{
    return { &node == range.start.container.ptr() ? range.start.offset : 0,
        &node == range.end.container.ptr() ? range.end.offset : std::numeric_limits<unsigned>::max() };
}

static RefPtr<Node> firstIntersectingNode(const SimpleRange& range)
{
    if (range.start.container->isCharacterDataNode())
        return range.start.container.ptr();
    if (auto child = range.start.container->traverseToChildAt(range.start.offset))
        return child;
    return NodeTraversal::nextSkippingChildren(range.start.container);
}

static RefPtr<Node> nodePastLastIntersectingNode(const SimpleRange& range)
{
    if (range.end.container->isCharacterDataNode())
        return NodeTraversal::nextSkippingChildren(range.end.container);
    if (auto child = range.end.container->traverseToChildAt(range.end.offset))
        return child;
    return NodeTraversal::nextSkippingChildren(range.end.container);
}

static RefPtr<Node> firstIntersectingNodeWithDeprecatedZeroOffsetStartQuirk(const SimpleRange& range)
{
    if (range.start.container->isCharacterDataNode())
        return range.start.container.ptr();
    if (auto child = range.start.container->traverseToChildAt(range.start.offset))
        return child;
    if (!range.start.offset)
        return range.start.container.ptr();
    return NodeTraversal::nextSkippingChildren(range.start.container);
}

IntersectingNodeIterator::IntersectingNodeIterator(const SimpleRange& range)
    : m_node(firstIntersectingNode(range))
    , m_pastLastNode(nodePastLastIntersectingNode(range))
{
    enforceEndInvariant();
}

IntersectingNodeIterator::IntersectingNodeIterator(const SimpleRange& range, QuirkFlag)
    : m_node(firstIntersectingNodeWithDeprecatedZeroOffsetStartQuirk(range))
    , m_pastLastNode(nodePastLastIntersectingNode(range))
{
    enforceEndInvariant();
}

void IntersectingNodeIterator::advance()
{
    ASSERT(m_node);
    m_node = NodeTraversal::next(*m_node);
    enforceEndInvariant();
}

void IntersectingNodeIterator::advanceSkippingChildren()
{
    ASSERT(m_node);
    m_node = m_node->contains(m_pastLastNode.get()) ? nullptr : NodeTraversal::nextSkippingChildren(*m_node);
    enforceEndInvariant();
}

void IntersectingNodeIterator::enforceEndInvariant()
{
    if (m_node == m_pastLastNode || !m_node) {
        m_node = nullptr;
        m_pastLastNode = nullptr;
    }
}

template<TreeType treeType> Node* commonInclusiveAncestor(const SimpleRange& range)
{
    return commonInclusiveAncestor<treeType>(range.start.container, range.end.container);
}

template Node* commonInclusiveAncestor<ComposedTree>(const SimpleRange&);

template<TreeType treeType> bool contains(const SimpleRange& range, const BoundaryPoint& point)
{
    return is_lteq(treeOrder<treeType>(range.start, point)) && is_lteq(treeOrder<treeType>(point, range.end));
}

template bool contains<Tree>(const SimpleRange&, const BoundaryPoint&);

template<TreeType treeType> bool contains(const SimpleRange& range, const std::optional<BoundaryPoint>& point)
{
    return point && contains<treeType>(range, *point);
}

template bool contains<ComposedTree>(const SimpleRange&, const std::optional<BoundaryPoint>&);

bool containsForTesting(TreeType type, const SimpleRange& range, const BoundaryPoint& point)
{
    switch (type) {
    case Tree:
        return contains<Tree>(range, point);
    case ShadowIncludingTree:
        return contains<ShadowIncludingTree>(range, point);
    case ComposedTree:
        return contains<ComposedTree>(range, point);
    }
    ASSERT_NOT_REACHED();
    return false;
}

template<TreeType treeType> PartialOrdering treeOrder(const SimpleRange& range, const BoundaryPoint& point)
{
    if (auto order = treeOrder<treeType>(range.start, point); !is_lt(order))
        return order;
    if (auto order = treeOrder<treeType>(range.end, point); !is_gt(order))
        return order;
    return PartialOrdering::equivalent;
}

template<TreeType treeType> PartialOrdering treeOrder(const BoundaryPoint& point, const SimpleRange& range)
{
    if (auto order = treeOrder<treeType>(point, range.start); !is_gt(order))
        return order;
    if (auto order = treeOrder<treeType>(point, range.end); !is_lt(order))
        return order;
    return PartialOrdering::equivalent;
}

template PartialOrdering treeOrder<Tree>(const SimpleRange&, const BoundaryPoint&);
template PartialOrdering treeOrder<Tree>(const BoundaryPoint&, const SimpleRange&);

template<TreeType treeType> bool contains(const SimpleRange& outerRange, const SimpleRange& innerRange)
{
    return is_lteq(treeOrder<treeType>(outerRange.start, innerRange.start)) && is_gteq(treeOrder<treeType>(outerRange.end, innerRange.end));
}

template bool contains<Tree>(const SimpleRange&, const SimpleRange&);
template bool contains<ComposedTree>(const SimpleRange&, const SimpleRange&);

bool containsForTesting(TreeType type, const SimpleRange& outerRange, const SimpleRange& innerRange)
{
    switch (type) {
    case Tree:
        return contains<Tree>(outerRange, innerRange);
    case ShadowIncludingTree:
        return contains<ShadowIncludingTree>(outerRange, innerRange);
    case ComposedTree:
        return contains<ComposedTree>(outerRange, innerRange);
    }
    ASSERT_NOT_REACHED();
    return false;
}

template<TreeType treeType> bool intersects(const SimpleRange& a, const SimpleRange& b)
{
    return is_lteq(treeOrder<treeType>(a.start, b.end)) && is_lteq(treeOrder<treeType>(b.start, a.end));
}

template bool intersects<Tree>(const SimpleRange&, const SimpleRange&);
template bool intersects<ComposedTree>(const SimpleRange&, const SimpleRange&);

bool intersectsForTesting(TreeType type, const SimpleRange& a, const SimpleRange& b)
{
    switch (type) {
    case Tree:
        return intersects<Tree>(a, b);
    case ShadowIncludingTree:
        return intersects<ShadowIncludingTree>(a, b);
    case ComposedTree:
        return intersects<ComposedTree>(a, b);
    }
    ASSERT_NOT_REACHED();
    return false;
}

static bool compareByComposedTreeOrder(const BoundaryPoint& a, const BoundaryPoint& b)
{
    return is_lt(treeOrder<ComposedTree>(a, b));
}

SimpleRange unionRange(const SimpleRange& a, const SimpleRange& b)
{
    return { std::min(a.start, b.start, compareByComposedTreeOrder), std::max(a.end, b.end, compareByComposedTreeOrder) };
}

std::optional<SimpleRange> intersection(const std::optional<SimpleRange>& a, const std::optional<SimpleRange>& b)
{
    // FIXME: Can this be done more efficiently, with fewer calls to treeOrder?
    if (!a || !b || !intersects<ComposedTree>(*a, *b))
        return std::nullopt;
    return { { std::max(a->start, b->start, compareByComposedTreeOrder), std::min(a->end, b->end, compareByComposedTreeOrder) } };
}

template<TreeType treeType> bool contains(const SimpleRange& range, const Node& node)
{
    // FIXME: Consider a more efficient algorithm that avoids always computing the node index.
    // FIXME: Does this const_cast point to a design problem?
    auto nodeRange = makeRangeSelectingNode(const_cast<Node&>(node));
    return nodeRange && contains<treeType>(range, *nodeRange);
}

template bool contains<Tree>(const SimpleRange&, const Node&);
template bool contains<ComposedTree>(const SimpleRange&, const Node&);

bool containsForTesting(TreeType type, const SimpleRange& range, const Node& node)
{
    switch (type) {
    case Tree:
        return contains<Tree>(range, node);
    case ShadowIncludingTree:
        return contains<ShadowIncludingTree>(range, node);
    case ComposedTree:
        return contains<ComposedTree>(range, node);
    }
    ASSERT_NOT_REACHED();
    return false;
}

template<TreeType treeType> bool contains(const Node& outer, const Node& inner)
{
    for (auto inclusiveAncestor = &inner; inclusiveAncestor; inclusiveAncestor = parent<treeType>(*inclusiveAncestor)) {
        if (inclusiveAncestor == &outer)
            return true;
    }
    return false;
}

template<> bool contains<Tree>(const Node& outer, const Node& inner)
{
    // We specialize here because we want to take advantage of optimizations in Node::isDescendantOf.
    return outer.contains(inner);
}

template<TreeType treeType> bool intersects(const SimpleRange& range, const Node& node)
{
    // FIXME: Consider a more efficient algorithm that avoids always computing the node index.
    // FIXME: Does this const_cast point to a design problem?
    auto nodeRange = makeRangeSelectingNode(const_cast<Node&>(node));
    if (!nodeRange)
        return contains<treeType>(node, range.start.container);
    return is_lt(treeOrder<treeType>(nodeRange->start, range.end)) && is_lt(treeOrder<treeType>(range.start, nodeRange->end));
}

template bool intersects<Tree>(const SimpleRange&, const Node&);
template bool intersects<ComposedTree>(const SimpleRange&, const Node&);

bool intersectsForTesting(TreeType type, const SimpleRange& range, const Node& node)
{
    switch (type) {
    case Tree:
        return intersects<Tree>(range, node);
    case ShadowIncludingTree:
        return intersects<ShadowIncludingTree>(range, node);
    case ComposedTree:
        return intersects<ComposedTree>(range, node);
    }
    ASSERT_NOT_REACHED();
    return false;
}

bool containsCrossingDocumentBoundaries(const SimpleRange& range, Node& node)
{
    auto* ancestor = &node;
    while (&range.start.document() != &ancestor->document()) {
        ancestor = ancestor->document().ownerElement();
        if (!ancestor)
            return false;
    }
    return contains<ComposedTree>(range, *ancestor);
}

}
