/*
    Copyright (C) 2004, 2005 Nikolas Zimmermann <wildfox@kde.org>
                  2004, 2005 Rob Buis <buis@kde.org>

    This file is part of the KDE project

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.
*/

#include "TraversalImpl.h"
#include <kdom/traversal/kdomtraversal.h>
#include "NodeFilterImpl.h"
#include "NodeImpl.h"
#include "kdom.h"

using namespace KDOM;

TraversalImpl::TraversalImpl(NodeImpl *n, short show,
                             NodeFilterImpl *nodeFilter,
                             bool expandEntityReferences)
: Shared(), m_root(n), m_whatToShow(show),
m_filter(nodeFilter), m_expandEntityReferences(expandEntityReferences)
{
    if(root())
        root()->ref();
    if(filter())
        filter()->ref();
}

TraversalImpl::~TraversalImpl()
{
    if(root())
        root()->deref();
    if(filter())
        filter()->deref();
}

short TraversalImpl::acceptNode(NodeImpl *node) const
{
    // FIXME: If XML is implemented we have to check expandEntityRerefences
    // in this function.  The bit twiddling here is done to map DOM node types,
    // which are given as integers from 1 through 12, to whatToShow bit masks.
    if(node && ((1 << (node->nodeType() - 1)) & m_whatToShow) != 0)
    // cast to short silences "enumeral and non-enumeral types in return" warning
        return m_filter ? m_filter->acceptNode(node) : static_cast<short>(FILTER_ACCEPT);

       return FILTER_SKIP;
}


NodeImpl *TraversalImpl::findParentNode(NodeImpl *node, short accept) const
{
    if(!node || node == root())
        return 0;
    NodeImpl *n = node->parentNode();
    while(n)
    {
        if(acceptNode(n) & accept)
            return n;
        if(n == root())
            return 0;
        n = n->parentNode();
    }

    return 0;
}

NodeImpl *TraversalImpl::findFirstChild(NodeImpl *node) const
{
    if(!node || acceptNode(node) == FILTER_REJECT)
        return 0;
    NodeImpl *n = node->firstChild();
    while(n)
    {
        if(acceptNode(n) == FILTER_ACCEPT)
            return n;
        n = n->nextSibling();
    }

    return 0;
}

NodeImpl *TraversalImpl::findLastChild(NodeImpl *node) const
{
    if(!node || acceptNode(node) == FILTER_REJECT)
    return 0;
    NodeImpl *n = node->lastChild();
    while(n)
    {
        if(acceptNode(n) == FILTER_ACCEPT)
            return n;
        n = n->previousSibling();
    }
    return 0;
}

NodeImpl *TraversalImpl::findPreviousSibling(NodeImpl *node) const
{
    if(!node)
        return 0;
    NodeImpl *n = node->previousSibling();
    while(n)
    {
        if(acceptNode(n) == FILTER_ACCEPT)
            return n;
        n = n->previousSibling();
    }
    return 0;
}

NodeImpl *TraversalImpl::findNextSibling(NodeImpl *node) const
{
    if(!node)
    return 0;
    NodeImpl *n = node->nextSibling();
    while(n)
    {
        if(acceptNode(n) == FILTER_ACCEPT)
            return n;
        n = n->nextSibling();
    }
    return 0;
}

NodeImpl *TraversalImpl::findLastDescendant(NodeImpl *node) const
{
    NodeImpl *n = node;
    NodeImpl *r = node;
    while(n)
    {
        short accepted = acceptNode(n);
        if(accepted != FILTER_REJECT)
        {
            if(accepted == FILTER_ACCEPT)
                r = n;
            if(n->lastChild())
                n = n->lastChild();
            else if(n != node && n->previousSibling())
                n = n->previousSibling();
            else
                break;
        }
        else
            break;
    }

    return r;
}

NodeImpl *TraversalImpl::findPreviousNode(NodeImpl *node) const
{
    NodeImpl *n = node->previousSibling();
    while(n)
    {
        short accepted = acceptNode(n);
        if(accepted != FILTER_REJECT)
        {
            NodeImpl *d = findLastDescendant(n);
            if(acceptNode(d) == FILTER_ACCEPT)
                return d;
            // else FILTER_SKIP
        }
        n = n->previousSibling();
    }

    return findParentNode(node);
}

NodeImpl *TraversalImpl::findNextNode(NodeImpl *node) const
{
    NodeImpl *n = node->firstChild();
    while(n)
    {
        switch(acceptNode(n))
        {
        case FILTER_ACCEPT:
            return n;
        case FILTER_SKIP:
            if(n->firstChild())
                n = n->firstChild();
            else
                n = n->nextSibling();
            break;
        case FILTER_REJECT:
            n = n->nextSibling();
            break;
        }
    }

    n = node->nextSibling();
    while(n)
    {
        switch(acceptNode(n))
        {
        case FILTER_ACCEPT:
            return n;
        case FILTER_SKIP:
            return findNextNode(n);
        case FILTER_REJECT:
            n = n->nextSibling();
        break;
        }
    }

    NodeImpl *parent = findParentNode(node, FILTER_ACCEPT | FILTER_SKIP);
    while(parent)
    {
        n = parent->nextSibling();
        while(n)
        {
            switch(acceptNode(n))
            {
            case FILTER_ACCEPT:
                return n;
            case FILTER_SKIP:
                return findNextNode(n);
            case FILTER_REJECT:
                n = n->nextSibling();
                break;
            }
        }
        parent = findParentNode(parent, FILTER_ACCEPT | FILTER_SKIP);
    }

    return 0;
}

