/*
 * Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies)
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */

#include "config.h"

#include "AreaAllocator.h"

namespace WebKit {

AreaAllocator::AreaAllocator(const WebCore::IntSize& size)
    : m_size(size)
    , m_minAlloc(1, 1)
    , m_margin(0, 0)
{
}

AreaAllocator::~AreaAllocator()
{
}

void AreaAllocator::expand(const WebCore::IntSize& size)
{
    m_size = m_size.expandedTo(size);
}

void AreaAllocator::expandBy(const WebCore::IntSize& size)
{
    m_size += size;
}

void AreaAllocator::release(const WebCore::IntRect&)
{
}

int AreaAllocator::overhead() const
{
    return 0;
}

WebCore::IntSize AreaAllocator::roundAllocation(const WebCore::IntSize& size) const
{
    int width = size.width() + m_margin.width();
    int height = size.height() + m_margin.height();
    int extra = width % m_minAlloc.width();
    if (extra)
        width += m_minAlloc.width() - extra;
    extra = height % m_minAlloc.height();
    if (extra)
        height += m_minAlloc.height() - extra;

    return WebCore::IntSize(width, height);
}

GeneralAreaAllocator::GeneralAreaAllocator(const WebCore::IntSize& size)
    : AreaAllocator(WebCore::nextPowerOfTwo(size))
{
    m_root = new Node();
    m_root->rect = WebCore::IntRect(0, 0, m_size.width(), m_size.height());
    m_root->largestFree = m_size;
    m_root->parent = 0;
    m_root->left = 0;
    m_root->right = 0;
    m_nodeCount = 1;
    setMinimumAllocation(WebCore::IntSize(8, 8));
}

GeneralAreaAllocator::~GeneralAreaAllocator()
{
    freeNode(m_root);
}

void GeneralAreaAllocator::freeNode(Node* node)
{
    if (node) {
        freeNode(node->left);
        freeNode(node->right);
    }
    delete node;
}

void GeneralAreaAllocator::expand(const WebCore::IntSize& size)
{
    AreaAllocator::expand(WebCore::nextPowerOfTwo(size));

    if (m_root->rect.size() == m_size)
        return; // No change.

    if (!m_root->left && m_root->largestFree.width() > 0) {
        // No allocations have occurred, so just adjust the root size.
        m_root->rect = WebCore::IntRect(0, 0, m_size.width(), m_size.height());
        m_root->largestFree = m_size;
        return;
    }

    // Add extra nodes above the current root to expand the tree.
    Node* oldRoot = m_root;
    Split split;
    if (m_size.width() >= m_size.height())
        split = SplitOnX;
    else
        split = SplitOnY;

    while (m_root->rect.size() != m_size) {
        if (m_root->rect.width() == m_size.width())
            split = SplitOnY;
        else if (m_root->rect.height() == m_size.height())
            split = SplitOnX;
        Node* parent = new Node();
        Node* right = new Node();
        m_nodeCount += 2;
        m_root->parent = parent;
        parent->parent = 0;
        parent->left = m_root;
        parent->right = right;
        parent->largestFree = m_root->rect.size();
        right->parent = parent;
        right->left = 0;
        right->right = 0;
        right->largestFree = m_root->rect.size();
        if (split == SplitOnX) {
            parent->rect = WebCore::IntRect(m_root->rect.x(), m_root->rect.y(),
                                            m_root->rect.width() * 2, m_root->rect.height());
            right->rect = WebCore::IntRect(m_root->rect.x() + m_root->rect.width(), m_root->rect.y(),
                                           m_root->rect.width(), m_root->rect.height());
        } else {
            parent->rect = WebCore::IntRect(m_root->rect.x(), m_root->rect.y(),
                                            m_root->rect.width(), m_root->rect.height() * 2);
            right->rect = WebCore::IntRect(m_root->rect.x(), m_root->rect.y() + m_root->rect.width(),
                                           m_root->rect.width(), m_root->rect.height());
        }
        split = (split == SplitOnX ? SplitOnY : SplitOnX);
        m_root = parent;
    }
    updateLargestFree(oldRoot);
}

static inline bool fitsWithin(const WebCore::IntSize& size1, const WebCore::IntSize& size2)
{
    return size1.width() <= size2.width() && size1.height() <= size2.height();
}

WebCore::IntRect GeneralAreaAllocator::allocate(const WebCore::IntSize& size)
{
    WebCore::IntSize rounded = roundAllocation(size);
    rounded = WebCore::nextPowerOfTwo(rounded);
    if (rounded.width() <= 0 || rounded.width() > m_size.width()
        || rounded.height() <= 0 || rounded.height() > m_size.height())
        return WebCore::IntRect();

    WebCore::IntPoint point = allocateFromNode(rounded, m_root);
    if (point.x() >= 0)
        return WebCore::IntRect(point, size);
    return WebCore::IntRect();
}

WebCore::IntPoint GeneralAreaAllocator::allocateFromNode(const WebCore::IntSize& size, Node* node)
{
    // Find the best node to insert into, which should be
    // a node with the least amount of unused space that is
    // big enough to contain the requested size.
    while (node) {
        // Go down a level and determine if the left or right
        // sub-tree contains the best chance of allocation.
        Node* left = node->left;
        Node* right = node->right;
        if (left && fitsWithin(size, left->largestFree)) {
            if (right && fitsWithin(size, right->largestFree)) {
                if (left->largestFree.width() < right->largestFree.width()
                    || left->largestFree.height() < right->largestFree.height()) {
                    // The largestFree values may be a little oversized,
                    // so try the left sub-tree and then the right sub-tree.
                    WebCore::IntPoint point = allocateFromNode(size, left);
                    if (point.x() >= 0)
                        return point;
                    return allocateFromNode(size, right);
                }
                node = right;
            } else
                node = left;
        } else if (right && fitsWithin(size, right->largestFree))
            node = right;
        else if (left || right) {
            // Neither sub-node has enough space to allocate from.
            return WebCore::IntPoint(-1, -1);
        } else if (fitsWithin(size, node->largestFree)) {
            // Do we need to split this node into smaller pieces?
            Split split;
            if (fitsWithin(WebCore::IntSize(size.width() * 2, size.height() * 2), node->largestFree)) {
                // Split in either direction: choose the inverse of
                // the parent node's split direction to try to balance
                // out the wasted space as further subdivisions happen.
                if (node->parent
                    && node->parent->left->rect.x() == node->parent->right->rect.x())
                    split = SplitOnX;
                else if (node->parent)
                    split = SplitOnY;
                else if (node->rect.width() >= node->rect.height())
                    split = SplitOnX;
                else
                    split = SplitOnY;
            } else if (fitsWithin(WebCore::IntSize(size.width() * 2, size.height()), node->largestFree)) {
                // Split along the X direction.
                split = SplitOnX;
            } else if (fitsWithin(WebCore::IntSize(size.width(), size.height() * 2), node->largestFree)) {
                // Split along the Y direction.
                split = SplitOnY;
            } else {
                // Cannot split further - allocate this node.
                node->largestFree = WebCore::IntSize(0, 0);
                updateLargestFree(node);
                return node->rect.location();
            }

            // Split the node, then go around again using the left sub-tree.
            node = splitNode(node, split);
        } else {
            // Cannot possibly fit into this node.
            break;
        }
    }
    return WebCore::IntPoint(-1, -1);
}

GeneralAreaAllocator::Node* GeneralAreaAllocator::splitNode
    (Node* node, Split split)
{
    Node* left = new Node();
    Node* right = new Node();
    m_nodeCount += 2;
    left->parent = node;
    left->left = 0;
    left->right = 0;
    right->parent = node;
    right->left = 0;
    right->right = 0;
    node->left = left;
    node->right = right;

    if (split == SplitOnX) {
        left->rect = WebCore::IntRect(node->rect.x(), node->rect.y(),
                                      node->rect.width() / 2, node->rect.height());
        right->rect = WebCore::IntRect(left->rect.maxX(), node->rect.y(),
                                       node->rect.width() / 2, node->rect.height());
    } else {
        left->rect = WebCore::IntRect(node->rect.x(), node->rect.y(),
                                      node->rect.width(), node->rect.height() / 2);
        right->rect = WebCore::IntRect(node->rect.x(), left->rect.maxY(),
                                       node->rect.width(), node->rect.height() / 2);
    }

    left->largestFree = left->rect.size();
    right->largestFree = right->rect.size();
    node->largestFree = right->largestFree;
    return left;
}

void GeneralAreaAllocator::updateLargestFree(Node* node)
{
    while ((node = node->parent)) {
        node->largestFree = WebCore::IntSize(
                                std::max(node->left->largestFree.width(), node->right->largestFree.width()),
                                std::max(node->left->largestFree.height(), node->right->largestFree.height())
                            );
    }
}

void GeneralAreaAllocator::release(const WebCore::IntRect& rect)
{
    // Locate the node that contains the allocated region.
    Node* node = m_root;
    WebCore::IntPoint point = rect.location();
    while (node) {
        if (node->left && node->left->rect.contains(point))
            node = node->left;
        else if (node->right && node->right->rect.contains(point))
            node = node->right;
        else if (node->rect.contains(point))
            break;
        else
            return; // Point is completely outside the tree.
    }
    if (!node)
        return;

    // Mark the node as free and then work upwards through the tree
    // recombining and deleting nodes until we reach a sibling
    // that is still allocated.
    node->largestFree = node->rect.size();
    while (node->parent) {
        if (node->parent->left == node) {
            if (node->parent->right->largestFree != node->parent->right->rect.size())
                break;
        } else {
            if (node->parent->left->largestFree != node->parent->left->rect.size())
                break;
        }
        node = node->parent;
        freeNode(node->left);
        freeNode(node->right);
        m_nodeCount -= 2;
        node->left = 0;
        node->right = 0;
        node->largestFree = node->rect.size();
    }

    // Make the rest of our ancestors have the correct "largest free size".
    updateLargestFree(node);
}

int GeneralAreaAllocator::overhead() const
{
    return m_nodeCount * sizeof(Node);
}

} // namespace
