/*
 * This file is part of the HTML rendering engine for KDE.
 *
 * Copyright (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com)
 * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
 *
 * 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., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 *
 */

#include "config.h"
#include "CounterNode.h"

#include "RenderObject.h"
#include <stdio.h>

// FIXME: There's currently no strategy for getting the counter tree updated when new
// elements with counter-reset and counter-increment styles are added to the render tree.
// Also, the code can't handle changes where an existing node needs to change into a
// "reset" node, or from a "reset" node back to not a "reset" node. As of this writing,
// at least some of these problems manifest as failures in the t1204-increment and
// t1204-reset tests in the CSS 2.1 test suite.

namespace WebCore {

CounterNode::CounterNode(RenderObject* o, bool isReset, int value)
    : m_isReset(isReset)
    , m_value(value)
    , m_countInParent(0)
    , m_renderer(o)
    , m_parent(0)
    , m_previousSibling(0)
    , m_nextSibling(0)
    , m_firstChild(0)
    , m_lastChild(0)
{   
}

int CounterNode::computeCountInParent() const
{
    int increment = m_isReset ? 0 : m_value;
    if (m_previousSibling)
        return m_previousSibling->m_countInParent + increment;
    ASSERT(m_parent->m_firstChild == this);
    return m_parent->m_value + increment;
}

void CounterNode::recount()
{
    for (CounterNode* c = this; c; c = c->m_nextSibling) {
        int oldCount = c->m_countInParent;
        int newCount = c->computeCountInParent();
        c->m_countInParent = newCount;
        if (oldCount == newCount)
            break;
        if (c->m_renderer->isCounter())
            c->m_renderer->setNeedsLayoutAndPrefWidthsRecalc();
    }
}

void CounterNode::insertAfter(CounterNode* newChild, CounterNode* refChild)
{
    ASSERT(newChild);
    ASSERT(!newChild->m_parent);
    ASSERT(!newChild->m_previousSibling);
    ASSERT(!newChild->m_nextSibling);
    ASSERT(!refChild || refChild->m_parent == this);

    CounterNode* next;

    if (refChild) {
        next = refChild->m_nextSibling;
        refChild->m_nextSibling = newChild;
    } else {
        next = m_firstChild;
        m_firstChild = newChild;
    }

    if (next) {
        ASSERT(next->m_previousSibling == refChild);
        next->m_previousSibling = newChild;
    } else {
        ASSERT(m_lastChild == refChild);
        m_lastChild = newChild;
    }

    newChild->m_parent = this;
    newChild->m_previousSibling = refChild;
    newChild->m_nextSibling = next;

    newChild->m_countInParent = newChild->computeCountInParent();
    if (next)
        next->recount();
}

void CounterNode::removeChild(CounterNode* oldChild)
{
    ASSERT(oldChild);
    ASSERT(!oldChild->m_firstChild);
    ASSERT(!oldChild->m_lastChild);

    CounterNode* next = oldChild->m_nextSibling;
    CounterNode* prev = oldChild->m_previousSibling;

    oldChild->m_nextSibling = 0;
    oldChild->m_previousSibling = 0;
    oldChild->m_parent = 0;

    if (prev) 
        prev->m_nextSibling = next;
    else {
        ASSERT(m_firstChild == oldChild);
        m_firstChild = next;
    }
    
    if (next)
        next->m_previousSibling = prev;
    else {
        ASSERT(m_lastChild == oldChild);
        m_lastChild = prev;
    }
    
    if (next)
        next->recount();
}

#ifndef NDEBUG

static const CounterNode* nextInPreOrderAfterChildren(const CounterNode* node)
{
    CounterNode* next = node->nextSibling();
    if (!next) {
        next = node->parent();
        while (next && !next->nextSibling())
            next = next->parent();
        if (next)
            next = next->nextSibling();
    }
    return next;
}

static const CounterNode* nextInPreOrder(const CounterNode* node)
{
    if (CounterNode* child = node->firstChild())
        return child;
    return nextInPreOrderAfterChildren(node);
}

static void showTreeAndMark(const CounterNode* node)
{
    const CounterNode* root = node;
    while (root->parent())
        root = root->parent();

    for (const CounterNode* c = root; c; c = nextInPreOrder(c)) {
        if (c == node)
            fprintf(stderr, "*");                        
        for (const CounterNode* d = c; d && d != root; d = d->parent())
            fprintf(stderr, "\t");
        if (c->isReset())
            fprintf(stderr, "reset: %d\n", c->value());
        else
            fprintf(stderr, "increment: %d\n", c->value());
    }
}

#endif

} // namespace WebCore

#ifndef NDEBUG

void showTree(const WebCore::CounterNode* counter)
{
    if (counter)
        showTreeAndMark(counter);
}

#endif
