/*
 * 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:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
 * OWNER 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.
 */

#ifndef FlatTreeTraversal_h
#define FlatTreeTraversal_h

#include "core/CoreExport.h"
#include "core/dom/Document.h"
#include "core/dom/LayoutTreeBuilderTraversal.h"
#include "core/dom/shadow/InsertionPoint.h"
#include "core/dom/shadow/ShadowRoot.h"
#include "wtf/Allocator.h"

namespace blink {

class ContainerNode;
class HTMLSlotElement;
class Node;

// Flat tree version of |NodeTraversal|.
//
// None of member functions takes a |ShadowRoot| or an active insertion point,
// e.g. roughly speaking <content> and <shadow> in the shadow tree, see
// |InsertionPoint::isActive()| for details of active insertion points, since
// they aren't appeared in the flat tree. |assertPrecondition()| and
// |assertPostCondition()| check this condition.
//
// FIXME: Make some functions inline to optimise the performance.
// https://bugs.webkit.org/show_bug.cgi?id=82702
class CORE_EXPORT FlatTreeTraversal {
    STATIC_ONLY(FlatTreeTraversal);
public:
    typedef LayoutTreeBuilderTraversal::ParentDetails ParentTraversalDetails;

    static Node* next(const Node&);
    static Node* next(const Node&, const Node* stayWithin);
    static Node* previous(const Node&);

    static Node* firstChild(const Node&);
    static Node* lastChild(const Node&);
    static bool hasChildren(const Node&);

    static ContainerNode* parent(const Node&, ParentTraversalDetails* = 0);
    static Element* parentElement(const Node&);

    static Node* nextSibling(const Node&);
    static Node* previousSibling(const Node&);

    // Returns a child node at |index|. If |index| is greater than or equal to
    // the children, this function returns |nullptr|.
    static Node* childAt(const Node&, unsigned index);

    // Flat tree version of |NodeTraversal::nextSkippingChildren()|. This
    // function is similar to |next()| but skips child nodes of a specified
    // node.
    static Node* nextSkippingChildren(const Node&);
    static Node* nextSkippingChildren(const Node&, const Node* stayWithin);

    // Flat tree version of |NodeTraversal::previousSkippingChildren()|
    // similar to |previous()| but skipping child nodes of the specified node.
    static Node* previousSkippingChildren(const Node&);

    // Like previous, but visits parents before their children.
    static Node* previousPostOrder(const Node&, const Node* stayWithin = nullptr);

    // Flat tree version of |Node::isDescendantOf(other)|. This function
    // returns true if |other| contains |node|, otherwise returns
    // false. If |other| is |node|, this function returns false.
    static bool isDescendantOf(const Node& /*node*/, const Node& other);

    static bool contains(const ContainerNode& container, const Node& node)
    {
        assertPrecondition(container);
        assertPrecondition(node);
        return container == node || isDescendantOf(node, container);
    }

    static bool containsIncludingPseudoElement(const ContainerNode&, const Node&);

    // Returns a common ancestor of |nodeA| and |nodeB| if exists, otherwise
    // returns |nullptr|.
    static Node* commonAncestor(const Node& nodeA, const Node& nodeB);

    // Flat tree version of |Node::nodeIndex()|. This function returns a
    // zero base position number of the specified node in child nodes list, or
    // zero if the specified node has no parent.
    static unsigned index(const Node&);

    // Flat tree version of |ContainerNode::countChildren()|. This function
    // returns the number of the child nodes of the specified node in the
    // flat tree.
    static unsigned countChildren(const Node&);

    static Node* lastWithin(const Node&);
    static Node& lastWithinOrSelf(const Node&);

private:
    enum TraversalDirection {
        TraversalDirectionForward,
        TraversalDirectionBackward
    };

    static void assertPrecondition(const Node& node)
    {
        DCHECK(!node.needsDistributionRecalc());
        DCHECK(node.canParticipateInFlatTree());
    }

    static void assertPostcondition(const Node* node)
    {
#if DCHECK_IS_ON()
        if (node)
            assertPrecondition(*node);
#endif
    }

    static Node* resolveDistributionStartingAt(const Node*, TraversalDirection);
    static Node* v0ResolveDistributionStartingAt(const Node&, TraversalDirection);

    static Node* traverseNext(const Node&);
    static Node* traverseNext(const Node&, const Node* stayWithin);
    static Node* traverseNextSkippingChildren(const Node&, const Node* stayWithin);
    static Node* traversePrevious(const Node&);

    static Node* traverseFirstChild(const Node&);
    static Node* traverseLastChild(const Node&);
    static Node* traverseChild(const Node&, TraversalDirection);

    static ContainerNode* traverseParent(const Node&, ParentTraversalDetails* = 0);
    // TODO(hayato): Make ParentTraversalDetails be aware of slot elements too.
    static ContainerNode* traverseParentForV0(const Node&,  ParentTraversalDetails* = 0);
    static ContainerNode* traverseParentOrHost(const Node&);

    static Node* traverseNextSibling(const Node&);
    static Node* traversePreviousSibling(const Node&);

    static Node* traverseSiblings(const Node&, TraversalDirection);
    static Node* traverseSiblingsForV1HostChild(const Node&, TraversalDirection);
    static Node* traverseSiblingsForV0Distribution(const Node&, TraversalDirection);

    static Node* traverseNextAncestorSibling(const Node&);
    static Node* traversePreviousAncestorSibling(const Node&);
};

inline ContainerNode* FlatTreeTraversal::parent(const Node& node, ParentTraversalDetails* details)
{
    assertPrecondition(node);
    ContainerNode* result = traverseParent(node, details);
    assertPostcondition(result);
    return result;
}

inline Element* FlatTreeTraversal::parentElement(const Node& node)
{
    ContainerNode* parent = FlatTreeTraversal::parent(node);
    return parent && parent->isElementNode() ? toElement(parent) : nullptr;
}

inline Node* FlatTreeTraversal::nextSibling(const Node& node)
{
    assertPrecondition(node);
    Node* result = traverseSiblings(node, TraversalDirectionForward);
    assertPostcondition(result);
    return result;
}

inline Node* FlatTreeTraversal::previousSibling(const Node& node)
{
    assertPrecondition(node);
    Node* result = traverseSiblings(node, TraversalDirectionBackward);
    assertPostcondition(result);
    return result;
}

inline Node* FlatTreeTraversal::next(const Node& node)
{
    assertPrecondition(node);
    Node* result = traverseNext(node);
    assertPostcondition(result);
    return result;
}

inline Node* FlatTreeTraversal::next(const Node& node, const Node* stayWithin)
{
    assertPrecondition(node);
    Node* result = traverseNext(node, stayWithin);
    assertPostcondition(result);
    return result;
}

inline Node* FlatTreeTraversal::nextSkippingChildren(const Node& node, const Node* stayWithin)
{
    assertPrecondition(node);
    Node* result = traverseNextSkippingChildren(node, stayWithin);
    assertPostcondition(result);
    return result;
}

inline Node* FlatTreeTraversal::traverseNext(const Node& node)
{
    if (Node* next = traverseFirstChild(node))
        return next;
    for (const Node* next = &node; next; next = traverseParent(*next)) {
        if (Node* sibling = traverseNextSibling(*next))
            return sibling;
    }
    return nullptr;
}

inline Node* FlatTreeTraversal::traverseNext(const Node& node, const Node* stayWithin)
{
    if (Node* next = traverseFirstChild(node))
        return next;
    return traverseNextSkippingChildren(node, stayWithin);
}

inline Node* FlatTreeTraversal::traverseNextSkippingChildren(const Node& node, const Node* stayWithin)
{
    for (const Node* next = &node; next; next = traverseParent(*next)) {
        if (next == stayWithin)
            return nullptr;
        if (Node* sibling = traverseNextSibling(*next))
            return sibling;
    }
    return nullptr;
}

inline Node* FlatTreeTraversal::previous(const Node& node)
{
    assertPrecondition(node);
    Node* result = traversePrevious(node);
    assertPostcondition(result);
    return result;
}

inline Node* FlatTreeTraversal::traversePrevious(const Node& node)
{
    if (Node* previous = traversePreviousSibling(node)) {
        while (Node* child = traverseLastChild(*previous))
            previous = child;
        return previous;
    }
    return traverseParent(node);
}

inline Node* FlatTreeTraversal::firstChild(const Node& node)
{
    assertPrecondition(node);
    Node* result = traverseChild(node, TraversalDirectionForward);
    assertPostcondition(result);
    return result;
}

inline Node* FlatTreeTraversal::lastChild(const Node& node)
{
    assertPrecondition(node);
    Node* result = traverseLastChild(node);
    assertPostcondition(result);
    return result;
}

inline bool FlatTreeTraversal::hasChildren(const Node& node)
{
    return firstChild(node);
}

inline Node* FlatTreeTraversal::traverseNextSibling(const Node& node)
{
    return traverseSiblings(node, TraversalDirectionForward);
}

inline Node* FlatTreeTraversal::traversePreviousSibling(const Node& node)
{
    return traverseSiblings(node, TraversalDirectionBackward);
}

inline Node* FlatTreeTraversal::traverseFirstChild(const Node& node)
{
    return traverseChild(node, TraversalDirectionForward);
}

inline Node* FlatTreeTraversal::traverseLastChild(const Node& node)
{
    return traverseChild(node, TraversalDirectionBackward);
}

} // namespace blink

#endif
