/*
 * Copyright (C) 2018 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.
 */

#pragma once

#if ENABLE(LAYOUT_FORMATTING_CONTEXT)

namespace WebCore {
namespace Layout {

template <typename T>
class LayoutIterator {
public:
    LayoutIterator(const Container* root);
    LayoutIterator(const Container* root, const T* current);

    const T& operator*() const;
    const T* operator->() const;

    bool operator==(const LayoutIterator& other) const;
    bool operator!=(const LayoutIterator& other) const;

    LayoutIterator& traverseNext();
    LayoutIterator& traverseNextSibling();
    LayoutIterator& traversePreviousSibling();
    LayoutIterator& traverseAncestor();

private:
    const Container* m_root;
    const T* m_current;
};

// Similar to WTF::is<>() but without the static_assert() making sure the check is necessary.
template <typename T, typename U>
inline bool isLayoutBoxOfType(const U& layoutBox) { return TypeCastTraits<const T, const U>::isOfType(layoutBox); }

namespace LayoutBoxTraversal {

template <typename U>
inline const Box* firstChild(U& object)
{
    return object.firstChild();
}

inline const Box* firstChild(const Box&)
{
    return nullptr;
}

inline const Box* nextAncestorSibling(const Box& current, const Container* stayWithin)
{
    for (auto* ancestor = current.parent(); ancestor; ancestor = ancestor->parent()) {
        if (ancestor == stayWithin)
            return nullptr;
        if (auto* sibling = ancestor->nextSibling())
            return sibling;
    }
    return nullptr;
}

template <typename U>
inline const Box* next(const U& current, const Container* stayWithin)
{
    if (auto* child = firstChild(current))
        return child;

    if (&current == stayWithin)
        return nullptr;

    if (auto* sibling = current.nextSibling())
        return sibling;

    return nextAncestorSibling(current, stayWithin);
}

inline const Box* nextSkippingChildren(Box& current, const Container* stayWithin)
{
    if (&current == stayWithin)
        return nullptr;

    if (auto* sibling = current.nextSibling())
        return sibling;

    return nextAncestorSibling(current, stayWithin);
}

}
// Traversal helpers
namespace Traversal {

template <typename T, typename U>
inline const T* firstChild(U& current)
{
    auto* object = LayoutBoxTraversal::firstChild(current);
    while (object && !isLayoutBoxOfType<T>(*object))
        object = object->nextSibling();
    return static_cast<const T*>(object);
}

template <typename T, typename U>
inline const T* lastChild(U& current)
{
    auto* object = current.lastChild();
    while (object && !isLayoutBoxOfType<T>(*object))
        object = object->previousSibling();
    return static_cast<const T*>(object);
}

template <typename T>
inline const T* nextSibling(const T& current)
{
    auto* object = current.nextSibling();
    while (object && !isLayoutBoxOfType<T>(*object))
        object = object->nextSibling();
    return static_cast<const T*>(object);
}

template <typename T, typename U>
inline const T* previousSibling(const T& current)
{
    auto* object = current.previousSibling();
    while (object && !isLayoutBoxOfType<T>(*object))
        object = object->previousSibling();
    return static_cast<const T*>(object);
}

template <typename T, typename U>
inline const T* findAncestorOfType(const T& current)
{
    for (auto* ancestor = current.parent(); ancestor; ancestor = ancestor->parent()) {
        if (isLayoutBoxOfType<T>(*ancestor))
            return static_cast<const T*>(ancestor);
    }
    return nullptr;
}

template <typename T, typename U>
inline const T* firstWithin(const U& stayWithin)
{
    auto* descendant = LayoutBoxTraversal::firstChild(stayWithin);
    while (descendant && !isLayoutBoxOfType<T>(*descendant))
        descendant = LayoutBoxTraversal::next(*descendant, &stayWithin);
    return static_cast<const T*>(descendant);
}

template <typename T, typename U>
inline const T* next(const U& current, const Container* stayWithin)
{
    auto* descendant = LayoutBoxTraversal::next(current, stayWithin);
    while (descendant && !isLayoutBoxOfType<T>(*descendant))
        descendant = LayoutBoxTraversal::next(*descendant, stayWithin);
    return static_cast<const T*>(descendant);
}

}

// LayoutIterator

template <typename T>
inline LayoutIterator<T>::LayoutIterator(const Container* root)
    : m_root(root)
    , m_current(nullptr)
{
}

template <typename T>
inline LayoutIterator<T>::LayoutIterator(const Container* root, const T* current)
    : m_root(root)
    , m_current(current)
{
}

template <typename T>
inline LayoutIterator<T>& LayoutIterator<T>::traverseNextSibling()
{
    ASSERT(m_current);
    m_current = Traversal::nextSibling<T>(*m_current);
    return *this;
}

template <typename T>
inline LayoutIterator<T>& LayoutIterator<T>::traverseNext()
{
    ASSERT(m_current);
    m_current = Traversal::next<T>(*m_current, m_root);
    return *this;
}

template <typename T>
inline LayoutIterator<T>& LayoutIterator<T>::traversePreviousSibling()
{
    ASSERT(m_current);
    m_current = Traversal::previousSibling<T>(*m_current);
    return *this;
}

template <typename T>
inline LayoutIterator<T>& LayoutIterator<T>::traverseAncestor()
{
    ASSERT(m_current);
    ASSERT(m_current != m_root);
    m_current = Traversal::findAncestorOfType<T>(*m_current);
    return *this;
}

template <typename T>
inline const T& LayoutIterator<T>::operator*() const
{
    ASSERT(m_current);
    return *m_current;
}

template <typename T>
inline const T* LayoutIterator<T>::operator->() const
{
    ASSERT(m_current);
    return m_current;
}

template <typename T>
inline bool LayoutIterator<T>::operator==(const LayoutIterator& other) const
{
    ASSERT(m_root == other.m_root);
    return m_current == other.m_current;
}

template <typename T>
inline bool LayoutIterator<T>::operator!=(const LayoutIterator& other) const
{
    return !(*this == other);
}

}
}
#include "LayoutAncestorIterator.h"
#include "LayoutChildIterator.h"

#endif
