/**
 * Copyright (C) 2004 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 "RenderCounter.h"

#include "CounterNode.h"
#include "Document.h"
#include "HTMLNames.h"
#include "HTMLOListElement.h"
#include "RenderListItem.h"
#include "RenderListMarker.h"
#include "RenderStyle.h"

namespace WebCore {

using namespace HTMLNames;

typedef HashMap<RefPtr<AtomicStringImpl>, CounterNode*> CounterMap;
typedef HashMap<const RenderObject*, CounterMap*> CounterMaps;

static CounterNode* counter(RenderObject*, const AtomicString& counterName, bool alwaysCreateCounter);

static CounterMaps& counterMaps()
{
    static CounterMaps staticCounterMaps;
    return staticCounterMaps;
}

static inline RenderObject* previousSiblingOrParent(RenderObject* object)
{
    if (RenderObject* sibling = object->previousSibling())
        return sibling;
    return object->parent();
}

static CounterNode* lastDescendant(CounterNode* node)
{
    CounterNode* last = node->lastChild();
    if (!last)
        return 0;

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

    return last;
}

static CounterNode* previousInPreOrder(CounterNode* node)
{
    CounterNode* previous = node->previousSibling();
    if (!previous)
        return node->parent();

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

    return previous;
}

static bool planCounter(RenderObject* object, const AtomicString& counterName, bool& isReset, int& value)
{
    ASSERT(object);

    // Real text nodes don't have their own style so they can't have counters.
    // We can't even look at their styles or we'll see extra resets and increments!
    if (object->isText() && !object->isBR())
        return false;

    RenderStyle* style = object->style();
    ASSERT(style);

    if (const CounterDirectiveMap* directivesMap = style->counterDirectives()) {
        CounterDirectives directives = directivesMap->get(counterName.impl());
        if (directives.m_reset) {
            value = directives.m_resetValue;
            if (directives.m_increment)
                value += directives.m_incrementValue;
            isReset = true;
            return true;
        }
        if (directives.m_increment) {
            value = directives.m_incrementValue;
            isReset = false;
            return true;
        }
    }

    if (counterName == "list-item") {
        if (object->isListItem()) {
            if (static_cast<RenderListItem*>(object)->hasExplicitValue()) {
                value = static_cast<RenderListItem*>(object)->explicitValue();
                isReset = true;
                return true;
            }
            value = 1;
            isReset = false;
            return true;
        }
        if (Node* e = object->element()) {
            if (e->hasTagName(olTag)) {
                value = static_cast<HTMLOListElement*>(e)->start();
                isReset = true;
                return true;
            }
            if (e->hasTagName(ulTag) || e->hasTagName(menuTag) || e->hasTagName(dirTag)) {
                value = 0;
                isReset = true;
                return true;
            }
        }
    }

    return false;
}

static bool findPlaceForCounter(RenderObject* object, const AtomicString& counterName,
    bool isReset, CounterNode*& parent, CounterNode*& previousSibling)
{
    // Find the appropriate previous sibling for insertion into the parent node
    // by searching in render tree order for a child of the counter.
    parent = 0;
    previousSibling = 0;
    RenderObject* resetCandidate = isReset ? object->parent() : previousSiblingOrParent(object);
    RenderObject* prevCounterCandidate = object;
    CounterNode* candidateCounter = 0;
    while ((prevCounterCandidate = prevCounterCandidate->previousInPreOrder())) {
        CounterNode* c = counter(prevCounterCandidate, counterName, false);
        if (prevCounterCandidate == resetCandidate) {
            if (!candidateCounter)
                candidateCounter = c;
            if (candidateCounter) {
                if (candidateCounter->isReset()) {
                    parent = candidateCounter;
                    previousSibling = 0;
                } else {
                    parent = candidateCounter->parent();
                    previousSibling = candidateCounter;
                }
                return true;
            }
            resetCandidate = previousSiblingOrParent(resetCandidate);
        } else if (c) {
            if (c->isReset())
                candidateCounter = 0;
            else if (!candidateCounter)
                candidateCounter = c;
        }
    }

    return false;
}

static CounterNode* counter(RenderObject* object, const AtomicString& counterName, bool alwaysCreateCounter)
{
    ASSERT(object);

    if (object->m_hasCounterNodeMap)
        if (CounterMap* nodeMap = counterMaps().get(object))
            if (CounterNode* node = nodeMap->get(counterName.impl()))
                return node;

    bool isReset = false;
    int value = 0;
    if (!planCounter(object, counterName, isReset, value) && !alwaysCreateCounter)
        return 0;

    CounterNode* newParent = 0;
    CounterNode* newPreviousSibling = 0;
    CounterNode* newNode;
    if (findPlaceForCounter(object, counterName, isReset, newParent, newPreviousSibling)) {
        newNode = new CounterNode(object, isReset, value);
        newParent->insertAfter(newNode, newPreviousSibling);
    } else {
        // Make a reset node for counters that aren't inside an existing reset node.
        newNode = new CounterNode(object, true, value);
    }

    CounterMap* nodeMap;
    if (object->m_hasCounterNodeMap)
        nodeMap = counterMaps().get(object);
    else {
        nodeMap = new CounterMap;
        counterMaps().set(object, nodeMap);
        object->m_hasCounterNodeMap = true;
    }
    nodeMap->set(counterName.impl(), newNode);

    return newNode;
}

RenderCounter::RenderCounter(Document* node, const CounterContent& counter)
    : RenderText(node, StringImpl::empty())
    , m_counter(counter)
    , m_counterNode(0)
{
}

const char* RenderCounter::renderName() const
{
    return "RenderCounter";
}

bool RenderCounter::isRenderCounter() const
{
    return true;
}

PassRefPtr<StringImpl> RenderCounter::originalText() const
{
    if (!parent())
        return 0;

    if (!m_counterNode)
        m_counterNode = counter(parent(), m_counter.identifier(), true);

    CounterNode* child = m_counterNode;
    int value = child->isReset() ? child->value() : child->countInParent();

    String text = listMarkerText(m_counter.listStyle(), value);

    if (!m_counter.separator().isNull()) {
        if (!child->isReset())
            child = child->parent();
        while (CounterNode* parent = child->parent()) {
            text = listMarkerText(m_counter.listStyle(), child->countInParent())
                + m_counter.separator() + text;
            child = parent;
        }
    }

    return text.impl();
}

void RenderCounter::dirtyLineBoxes(bool fullLayout, bool dummy)
{
    if (prefWidthsDirty())
        calcPrefWidths(0);
    RenderText::dirtyLineBoxes(fullLayout, dummy);
}

void RenderCounter::calcPrefWidths(int lead)
{
    setTextInternal(originalText());
    RenderText::calcPrefWidths(lead);
}

static void destroyCounterNodeChildren(AtomicStringImpl* identifier, CounterNode* node)
{
    CounterNode* previous;
    for (CounterNode* child = lastDescendant(node); child && child != node; child = previous) {
        previous = previousInPreOrder(child);
        child->parent()->removeChild(child);
        ASSERT(counterMaps().get(child->renderer())->get(identifier) == child);
        counterMaps().get(child->renderer())->remove(identifier);
        delete child;
    }
}

void RenderCounter::destroyCounterNodes(RenderObject* object)
{
    CounterMaps& maps = counterMaps();
    CounterMap* map = maps.get(object);
    if (!map)
        return;
    maps.remove(object);

    CounterMap::const_iterator end = map->end();
    for (CounterMap::const_iterator it = map->begin(); it != end; ++it) {
        CounterNode* node = it->second;
        destroyCounterNodeChildren(it->first.get(), node);
        if (CounterNode* parent = node->parent())
            parent->removeChild(node);
        delete node;
    }

    delete map;
}

} // namespace WebCore
