/*
 * Copyright (C) 2010 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "WebBackForwardList.h"

#include "WebPageProxy.h"

namespace WebKit {

static const unsigned DefaultCapacity = 100;

WebBackForwardList::WebBackForwardList(WebPageProxy* page)
    : m_page(page)
    , m_current(NoCurrentItemIndex)
    , m_capacity(DefaultCapacity)
    , m_closed(true)
    , m_enabled(true)
{
    ASSERT(m_current == NoCurrentItemIndex || m_current < m_entries.size());
}

WebBackForwardList::~WebBackForwardList()
{
}

void WebBackForwardList::pageClosed()
{
    if (m_page) {
        size_t size = m_entries.size();
        for (size_t i = 0; i < size; ++i)
            m_page->backForwardRemovedItem(m_entries[i]->itemID());
    }

    m_page = 0;
}

void WebBackForwardList::addItem(WebBackForwardListItem* newItem)
{
    ASSERT(m_current == NoCurrentItemIndex || m_current < m_entries.size());

    if (m_capacity == 0 || !m_enabled)
        return;

    Vector<RefPtr<APIObject> > removedItems;
    
    // Toss anything in the forward list    
    if (m_current != NoCurrentItemIndex) {
        unsigned targetSize = m_current + 1;
        removedItems.reserveCapacity(m_entries.size() - targetSize);
        while (m_entries.size() > targetSize) {
            if (m_page)
                m_page->backForwardRemovedItem(m_entries.last()->itemID());
            removedItems.append(m_entries.last().release());
            m_entries.removeLast();
        }
    }

    // Toss the first item if the list is getting too big, as long as we're not using it
    // (or even if we are, if we only want 1 entry).
    if (m_entries.size() == m_capacity && (m_current != 0 || m_capacity == 1)) {
        if (m_page)
            m_page->backForwardRemovedItem(m_entries[0]->itemID());
        removedItems.append(m_entries[0].release());
        m_entries.remove(0);
        m_current--;
    }

    m_entries.insert(m_current + 1, newItem);
    m_current++;

    if (m_page)
        m_page->didChangeBackForwardList(newItem, &removedItems);

    ASSERT(m_current == NoCurrentItemIndex || m_current < m_entries.size());
}

void WebBackForwardList::goToItem(WebBackForwardListItem* item)
{
    ASSERT(m_current == NoCurrentItemIndex || m_current < m_entries.size());

    if (!m_entries.size() || !item)
        return;
        
    unsigned index = 0;
    for (; index < m_entries.size(); ++index) {
        if (m_entries[index] == item)
            break;
    }
    if (index < m_entries.size()) {
        m_current = index;
        if (m_page)
            m_page->didChangeBackForwardList(0, 0);
    }
}

WebBackForwardListItem* WebBackForwardList::currentItem()
{
    ASSERT(m_current == NoCurrentItemIndex || m_current < m_entries.size());

    if (m_current != NoCurrentItemIndex)
        return m_entries[m_current].get();
    return 0;
}

WebBackForwardListItem* WebBackForwardList::backItem()
{
    ASSERT(m_current == NoCurrentItemIndex || m_current < m_entries.size());

    if (m_current && m_current != NoCurrentItemIndex)
        return m_entries[m_current - 1].get();
    return 0;
}

WebBackForwardListItem* WebBackForwardList::forwardItem()
{
    ASSERT(m_current == NoCurrentItemIndex || m_current < m_entries.size());

    if (m_entries.size() && m_current < m_entries.size() - 1)
        return m_entries[m_current + 1].get();
    return 0;
}

WebBackForwardListItem* WebBackForwardList::itemAtIndex(int index)
{
    ASSERT(m_current == NoCurrentItemIndex || m_current < m_entries.size());

    // Do range checks without doing math on index to avoid overflow.
    if (index < -static_cast<int>(m_current))
        return 0;
    
    if (index > forwardListCount())
        return 0;
        
    return m_entries[index + m_current].get();
}

int WebBackForwardList::backListCount()
{
    ASSERT(m_current == NoCurrentItemIndex || m_current < m_entries.size());

    return m_current == NoCurrentItemIndex ? 0 : m_current;
}

int WebBackForwardList::forwardListCount()
{
    ASSERT(m_current == NoCurrentItemIndex || m_current < m_entries.size());

    return m_current == NoCurrentItemIndex ? 0 : static_cast<int>(m_entries.size()) - (m_current + 1);
}

PassRefPtr<ImmutableArray> WebBackForwardList::backListAsImmutableArrayWithLimit(unsigned limit)
{
    ASSERT(m_current == NoCurrentItemIndex || m_current < m_entries.size());

    unsigned backListSize = static_cast<unsigned>(backListCount());
    unsigned size = std::min(backListSize, limit);
    if (!size)
        return ImmutableArray::create();

    Vector<RefPtr<APIObject> > vector;
    vector.reserveInitialCapacity(size);

    ASSERT(backListSize >= size);
    for (unsigned i = backListSize - size; i < backListSize; ++i)
        vector.uncheckedAppend(m_entries[i].get());

    return ImmutableArray::adopt(vector);
}

PassRefPtr<ImmutableArray> WebBackForwardList::forwardListAsImmutableArrayWithLimit(unsigned limit)
{
    ASSERT(m_current == NoCurrentItemIndex || m_current < m_entries.size());

    unsigned size = std::min(static_cast<unsigned>(forwardListCount()), limit);
    if (!size)
        return ImmutableArray::create();

    Vector<RefPtr<APIObject> > vector;
    vector.reserveInitialCapacity(size);

    unsigned last = m_current + size;
    ASSERT(last < m_entries.size());
    for (unsigned i = m_current + 1; i <= last; ++i)
        vector.uncheckedAppend(m_entries[i].get());

    return ImmutableArray::adopt(vector);
}

void WebBackForwardList::clear()
{
    ASSERT(m_current == NoCurrentItemIndex || m_current < m_entries.size());

    size_t size = m_entries.size();
    if (size <= 1)
        return;

    RefPtr<WebBackForwardListItem> currentItem = this->currentItem();

    if (m_page) {
        for (size_t i = 0; i < size; ++i) {
            if (m_entries[i] != currentItem)
                m_page->backForwardRemovedItem(m_entries[i]->itemID());
        }
    }

    Vector<RefPtr<APIObject> > removedItems;
    removedItems.reserveCapacity(m_entries.size() - 1);
    for (size_t i = 0; i < m_entries.size(); ++i) {
        if (i != m_current)
            removedItems.append(m_entries[i].release());
    }
    
    m_entries.shrink(1);
    m_entries[0] = currentItem.release();

    m_current = 0;

    if (m_page)
        m_page->didChangeBackForwardList(0, &removedItems);
}

} // namespace WebKit
