/*
 * 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); }

// Traversal helpers
namespace Traversal {

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

template <typename T>
inline const T* findAncestorOfType(const Box& 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* nextAncestorSibling(U& 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 T, typename U>
inline const T* nextWithin(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);
}

template <typename T, typename U>
inline const T* firstWithin(U& current)
{
    auto* descendant = current.fistChild();
    while (descendant && !isLayoutBoxOfType<T>(*descendant))
        descendant = nextWithin(*descendant, &current);
    return static_cast<const T*>(descendant);
}

template <typename T, typename U>
inline const T* next(U& current, const RenderObject* stayWithin)
{
    auto* descendant = nextWithin(current, stayWithin);
    while (descendant && !isLayoutBoxOfType<T>(*descendant))
        descendant = nextWithin(*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<const 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
