/*
 * 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 "RenderCounter.h"
#include "RenderElement.h"
#include <stdio.h>

namespace WebCore {

CounterNode::CounterNode(RenderElement& owner, bool hasResetType, int value)
    : m_hasResetType(hasResetType)
    , m_value(value)
    , m_countInParent(0)
    , m_owner(owner)
{
}

CounterNode::~CounterNode()
{
    // Ideally this would be an assert and this would never be reached. In reality this happens a lot
    // so we need to handle these cases. The node is still connected to the tree so we need to detach it.
    if (m_parent || m_previousSibling || m_nextSibling || m_firstChild || m_lastChild) {
        CounterNode* oldParent = nullptr;
        CounterNode* oldPreviousSibling = nullptr;
        // Instead of calling removeChild() we do this safely as the tree is likely broken if we get here.
        if (m_parent) {
            if (m_parent->m_firstChild == this)
                m_parent->m_firstChild = m_nextSibling;
            if (m_parent->m_lastChild == this)
                m_parent->m_lastChild = m_previousSibling;
            oldParent = m_parent;
            m_parent = nullptr;
        }
        if (m_previousSibling) {
            if (m_previousSibling->m_nextSibling == this)
                m_previousSibling->m_nextSibling = m_nextSibling;
            oldPreviousSibling = m_previousSibling;
            m_previousSibling = nullptr;
        }
        if (m_nextSibling) {
            if (m_nextSibling->m_previousSibling == this)
                m_nextSibling->m_previousSibling = oldPreviousSibling;
            m_nextSibling = nullptr;
        }
        if (m_firstChild) {
            // The node's children are reparented to the old parent.
            for (CounterNode* child = m_firstChild; child; ) {
                CounterNode* nextChild = child->m_nextSibling;
                CounterNode* nextSibling = nullptr;
                child->m_parent = oldParent;
                if (oldPreviousSibling) {
                    nextSibling = oldPreviousSibling->m_nextSibling;
                    child->m_previousSibling = oldPreviousSibling;
                    oldPreviousSibling->m_nextSibling = child;
                    child->m_nextSibling = nextSibling;
                    nextSibling->m_previousSibling = child;
                    oldPreviousSibling = child;
                }
                child = nextChild;
            }
        }
    }
    resetRenderers();
}

Ref<CounterNode> CounterNode::create(RenderElement& owner, bool hasResetType, int value)
{
    return adoptRef(*new CounterNode(owner, hasResetType, value));
}

CounterNode* CounterNode::nextInPreOrderAfterChildren(const CounterNode* stayWithin) const
{
    if (this == stayWithin)
        return nullptr;

    const CounterNode* current = this;
    CounterNode* next;
    while (!(next = current->m_nextSibling)) {
        current = current->m_parent;
        if (!current || current == stayWithin)
            return nullptr;
    }
    return next;
}

CounterNode* CounterNode::nextInPreOrder(const CounterNode* stayWithin) const
{
    if (CounterNode* next = m_firstChild)
        return next;

    return nextInPreOrderAfterChildren(stayWithin);
}

CounterNode* CounterNode::lastDescendant() const
{
    CounterNode* last = m_lastChild;
    if (!last)
        return nullptr;

    while (CounterNode* lastChild = last->m_lastChild)
        last = lastChild;

    return last;
}

CounterNode* CounterNode::previousInPreOrder() const
{
    CounterNode* previous = m_previousSibling;
    if (!previous)
        return m_parent;

    while (CounterNode* lastChild = previous->m_lastChild)
        previous = lastChild;

    return previous;
}

int CounterNode::computeCountInParent() const
{
    int increment = actsAsReset() ? 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::addRenderer(RenderCounter& renderer)
{
    ASSERT(!renderer.m_counterNode);
    ASSERT(!renderer.m_nextForSameCounter);
    renderer.m_nextForSameCounter = m_rootRenderer;
    m_rootRenderer = &renderer;
    renderer.m_counterNode = this;
}

void CounterNode::removeRenderer(RenderCounter& renderer)
{
    ASSERT(renderer.m_counterNode && renderer.m_counterNode == this);
    RenderCounter* previous = nullptr;
    for (auto* current = m_rootRenderer; current; previous = current, current = current->m_nextForSameCounter) {
        if (current != &renderer)
            continue;

        if (previous)
            previous->m_nextForSameCounter = renderer.m_nextForSameCounter;
        else
            m_rootRenderer = renderer.m_nextForSameCounter;
        renderer.m_nextForSameCounter = nullptr;
        renderer.m_counterNode = nullptr;
        return;
    }
    ASSERT_NOT_REACHED();
}

void CounterNode::resetRenderers()
{
    if (!m_rootRenderer)
        return;
    bool skipLayoutAndPerfWidthsRecalc = m_rootRenderer->renderTreeBeingDestroyed();
    auto* current = m_rootRenderer;
    while (current) {
        if (!skipLayoutAndPerfWidthsRecalc)
            current->setNeedsLayoutAndPrefWidthsRecalc();
        auto* next = current->m_nextForSameCounter;
        current->m_nextForSameCounter = nullptr;
        current->m_counterNode = nullptr;
        current = next;
    }
    m_rootRenderer = nullptr;
}

void CounterNode::resetThisAndDescendantsRenderers()
{
    CounterNode* node = this;
    do {
        node->resetRenderers();
        node = node->nextInPreOrder(this);
    } while (node);
}

void CounterNode::recount()
{
    for (CounterNode* node = this; node; node = node->m_nextSibling) {
        int oldCount = node->m_countInParent;
        int newCount = node->computeCountInParent();
        if (oldCount == newCount)
            break;
        node->m_countInParent = newCount;
        node->resetThisAndDescendantsRenderers();
    }
}

void CounterNode::insertAfter(CounterNode& newChild, CounterNode* beforeChild, const AtomicString& identifier)
{
    ASSERT(!newChild.m_parent);
    ASSERT(!newChild.m_previousSibling);
    ASSERT(!newChild.m_nextSibling);
    // If the beforeChild is not our child we can not complete the request. This hardens against bugs in RenderCounter.
    // When renderers are reparented it may request that we insert counter nodes improperly.
    if (beforeChild && beforeChild->m_parent != this)
        return;

    if (newChild.m_hasResetType) {
        while (m_lastChild != beforeChild)
            RenderCounter::destroyCounterNode(m_lastChild->owner(), identifier);
    }

    CounterNode* next;

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

    newChild.m_parent = this;
    newChild.m_previousSibling = beforeChild;

    if (next) {
        ASSERT(next->m_previousSibling == beforeChild);
        next->m_previousSibling = &newChild;
        newChild.m_nextSibling = next;
    } else {
        ASSERT(m_lastChild == beforeChild);
        m_lastChild = &newChild;
    }

    if (!newChild.m_firstChild || newChild.m_hasResetType) {
        newChild.m_countInParent = newChild.computeCountInParent();
        newChild.resetThisAndDescendantsRenderers();
        if (next)
            next->recount();
        return;
    }

    // The code below handles the case when a formerly root increment counter is loosing its root position
    // and therefore its children become next siblings.
    CounterNode* last = newChild.m_lastChild;
    CounterNode* first = newChild.m_firstChild;

    if (first) {
        ASSERT(last);
        newChild.m_nextSibling = first;
        if (m_lastChild == &newChild)
            m_lastChild = last;

        first->m_previousSibling = &newChild;
    
        // The case when the original next sibling of the inserted node becomes a child of
        // one of the former children of the inserted node is not handled as it is believed
        // to be impossible since:
        // 1. if the increment counter node lost it's root position as a result of another
        //    counter node being created, it will be inserted as the last child so next is null.
        // 2. if the increment counter node lost it's root position as a result of a renderer being
        //    inserted into the document's render tree, all its former children counters are attached
        //    to children of the inserted renderer and hence cannot be in scope for counter nodes
        //    attached to renderers that were already in the document's render tree.
        last->m_nextSibling = next;
        if (next) {
            ASSERT(next->m_previousSibling == &newChild);
            next->m_previousSibling = last;
        } else
            m_lastChild = last;
        for (next = first; ; next = next->m_nextSibling) {
            next->m_parent = this;
            if (last == next)
                break;
        }
    }
    newChild.m_firstChild = nullptr;
    newChild.m_lastChild = nullptr;
    newChild.m_countInParent = newChild.computeCountInParent();
    newChild.resetRenderers();
    first->recount();
}

void CounterNode::removeChild(CounterNode& oldChild)
{
    ASSERT(!oldChild.m_firstChild);
    ASSERT(!oldChild.m_lastChild);

    CounterNode* next = oldChild.m_nextSibling;
    CounterNode* previous = oldChild.m_previousSibling;

    oldChild.m_nextSibling = nullptr;
    oldChild.m_previousSibling = nullptr;
    oldChild.m_parent = nullptr;

    if (previous) 
        previous->m_nextSibling = next;
    else {
        ASSERT(m_firstChild == &oldChild);
        m_firstChild = next;
    }

    if (next)
        next->m_previousSibling = previous;
    else {
        ASSERT(m_lastChild == &oldChild);
        m_lastChild = previous;
    }

    if (next)
        next->recount();
}

#if ENABLE(TREE_DEBUGGING)

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

    for (const CounterNode* current = root; current; current = current->nextInPreOrder()) {
        fprintf(stderr, "%c", (current == node) ? '*' : ' ');
        for (const CounterNode* parent = current; parent && parent != root; parent = parent->parent())
            fprintf(stderr, "    ");
        fprintf(stderr, "%p %s: %d %d P:%p PS:%p NS:%p R:%p\n",
            current, current->actsAsReset() ? "reset____" : "increment", current->value(),
            current->countInParent(), current->parent(), current->previousSibling(),
            current->nextSibling(), &current->owner());
    }
    fflush(stderr);
}

#endif

} // namespace WebCore

#if ENABLE(TREE_DEBUGGING)

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

#endif
