/*
 * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
 *
 * 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.
 * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
 *     its contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE 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 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 "core/loader/HistoryController.h"

#include "core/dom/Document.h"
#include "core/history/HistoryItem.h"
#include "core/inspector/InspectorController.h"
#include "core/loader/DocumentLoader.h"
#include "core/loader/FrameLoader.h"
#include "core/frame/Frame.h"
#include "core/frame/FrameView.h"
#include "core/page/FrameTree.h"
#include "core/page/Page.h"
#include "platform/Logging.h"
#include "wtf/Deque.h"
#include "wtf/text/CString.h"

namespace WebCore {

PassOwnPtr<HistoryNode> HistoryNode::create(HistoryEntry* entry, HistoryItem* value)
{
    return adoptPtr(new HistoryNode(entry, value));
}

HistoryNode* HistoryNode::addChild(PassRefPtr<HistoryItem> item)
{
    m_children.append(HistoryNode::create(m_entry, item.get()));
    return m_children.last().get();
}

PassOwnPtr<HistoryNode> HistoryNode::cloneAndReplace(HistoryEntry* newEntry, HistoryItem* newItem, HistoryItem* oldItem, bool clipAtTarget, Frame* frame)
{
    bool isNodeBeingNavigated = m_value == oldItem;
    HistoryItem* itemForCreate = isNodeBeingNavigated ? newItem : m_value.get();
    OwnPtr<HistoryNode> newHistoryNode = create(newEntry, itemForCreate);

    if (!clipAtTarget || !isNodeBeingNavigated) {
        for (Frame* child = frame->tree().firstChild(); child; child = child->tree().nextSibling()) {
            HistoryNode* childHistoryNode = m_entry->m_framesToItems.get(child->frameID());
            if (!childHistoryNode)
                continue;
            newHistoryNode->m_children.append(childHistoryNode->cloneAndReplace(newEntry, newItem, oldItem, clipAtTarget, child));
        }
    }
    return newHistoryNode.release();
}

HistoryNode::HistoryNode(HistoryEntry* entry, HistoryItem* value)
    : m_entry(entry)
    , m_value(value)
{
    m_entry->m_framesToItems.add(value->targetFrameID(), this);
    String target = value->target();
    if (target.isNull())
        target = emptyString();
    m_entry->m_uniqueNamesToItems.add(target, this);
}

HistoryEntry::HistoryEntry(HistoryItem* root)
{
    m_root = HistoryNode::create(this, root);
}

PassOwnPtr<HistoryEntry> HistoryEntry::create(HistoryItem* root)
{
    return adoptPtr(new HistoryEntry(root));
}

PassOwnPtr<HistoryEntry> HistoryEntry::cloneAndReplace(HistoryItem* newItem, HistoryItem* oldItem, bool clipAtTarget, Page* page)
{
    OwnPtr<HistoryEntry> newEntry = adoptPtr(new HistoryEntry());
    newEntry->m_root = m_root->cloneAndReplace(newEntry.get(), newItem, oldItem, clipAtTarget, page->mainFrame());
    return newEntry.release();
}

HistoryNode* HistoryEntry::historyNodeForFrame(Frame* frame)
{
    if (HistoryNode* historyNode = m_framesToItems.get(frame->frameID()))
        return historyNode;
    String target = frame->tree().uniqueName();
    if (target.isNull())
        target = emptyString();
    return m_uniqueNamesToItems.get(target);
}

HistoryItem* HistoryEntry::itemForFrame(Frame* frame)
{
    if (HistoryNode* historyNode = historyNodeForFrame(frame))
        return historyNode->value();
    return 0;
}

HistoryController::HistoryController(Page* page)
    : m_page(page)
    , m_defersLoading(false)
{
}

HistoryController::~HistoryController()
{
}

void HistoryController::updateBackForwardListForFragmentScroll(Frame* frame)
{
    m_provisionalEntry.clear();
    createNewBackForwardItem(frame, false);
}

void HistoryController::goToEntry(PassOwnPtr<HistoryEntry> targetEntry)
{
    ASSERT(m_sameDocumentLoadsInProgress.isEmpty());
    ASSERT(m_differentDocumentLoadsInProgress.isEmpty());

    m_provisionalEntry = targetEntry;
    recursiveGoToEntry(m_page->mainFrame());

    if (m_differentDocumentLoadsInProgress.isEmpty()) {
        m_previousEntry = m_currentEntry.release();
        m_currentEntry = m_provisionalEntry.release();
    } else {
        m_page->mainFrame()->loader().stopAllLoaders();
    }

    for (HistoryFrameLoadSet::iterator it = m_sameDocumentLoadsInProgress.begin(); it != m_sameDocumentLoadsInProgress.end(); ++it)
        it->key->loader().loadHistoryItem(it->value, HistorySameDocumentLoad);
    for (HistoryFrameLoadSet::iterator it = m_differentDocumentLoadsInProgress.begin(); it != m_differentDocumentLoadsInProgress.end(); ++it)
        it->key->loader().loadHistoryItem(it->value, HistoryDifferentDocumentLoad);
    m_sameDocumentLoadsInProgress.clear();
    m_differentDocumentLoadsInProgress.clear();
}

void HistoryController::recursiveGoToEntry(Frame* frame)
{
    HistoryItem* newItem = m_provisionalEntry->itemForFrame(frame);
    HistoryItem* oldItem = m_currentEntry ? m_currentEntry->itemForFrame(frame) : 0;
    if (!newItem)
        return;

    if (!oldItem || (newItem != oldItem && newItem->itemSequenceNumber() != oldItem->itemSequenceNumber())) {
        if (oldItem && newItem->documentSequenceNumber() == oldItem->documentSequenceNumber())
            m_sameDocumentLoadsInProgress.set(frame, newItem);
        else
            m_differentDocumentLoadsInProgress.set(frame, newItem);
        return;
    }

    for (Frame* child = frame->tree().firstChild(); child; child = child->tree().nextSibling())
        recursiveGoToEntry(child);
}

void HistoryController::goToItem(HistoryItem* targetItem)
{
    if (m_defersLoading) {
        m_deferredItem = targetItem;
        return;
    }

    OwnPtr<HistoryEntry> newEntry = HistoryEntry::create(targetItem);
    Deque<HistoryNode*> historyNodes;
    historyNodes.append(newEntry->rootHistoryNode());
    while (!historyNodes.isEmpty()) {
        // For each item, read the children (if any) off the HistoryItem,
        // create a new HistoryNode for each child and attach it,
        // then clear the children on the HistoryItem.
        HistoryNode* historyNode = historyNodes.takeFirst();
        const HistoryItemVector& children = historyNode->value()->children();
        for (size_t i = 0; i < children.size(); i++) {
            HistoryNode* childHistoryNode = historyNode->addChild(children[i].get());
            historyNodes.append(childHistoryNode);
        }
        historyNode->value()->clearChildren();
    }
    goToEntry(newEntry.release());
}

void HistoryController::setDefersLoading(bool defer)
{
    m_defersLoading = defer;
    if (!defer && m_deferredItem) {
        goToItem(m_deferredItem.get());
        m_deferredItem = 0;
    }
}

// There are 2 things you might think of as "history", all of which are handled by these functions.
//
//     1) Back/forward: The m_currentItem is part of this mechanism.
//     2) Global history: Handled by the client.
//
void HistoryController::updateForStandardLoad(Frame* frame)
{
    LOG(History, "WebCoreHistory: Updating History for Standard Load in frame %s", frame->loader().documentLoader()->url().string().ascii().data());
    createNewBackForwardItem(frame, true);
}

void HistoryController::updateForInitialLoadInChildFrame(Frame* frame)
{
    ASSERT(frame->tree().parent());
    if (!m_currentEntry)
        return;
    if (HistoryNode* existingChildHistoryNode = m_currentEntry->historyNodeForFrame(frame))
        existingChildHistoryNode->updateValue(createItem(frame));
    else if (HistoryNode* parentHistoryNode = m_currentEntry->historyNodeForFrame(frame->tree().parent()))
        parentHistoryNode->addChild(createItem(frame));
}

void HistoryController::updateForCommit(Frame* frame)
{
#if !LOG_DISABLED
    if (frame->document())
        LOG(History, "WebCoreHistory: Updating History for commit in frame %s", frame->document()->title().utf8().data());
#endif
    FrameLoadType type = frame->loader().loadType();
    if (isBackForwardLoadType(type)) {
        // Once committed, we want to use current item for saving DocState, and
        // the provisional item for restoring state.
        // Note previousItem must be set before we close the URL, which will
        // happen when the data source is made non-provisional below
        if (m_provisionalEntry) {
            m_previousEntry = m_currentEntry.release();
            ASSERT(m_provisionalEntry);
            m_currentEntry = m_provisionalEntry.release();
        }
        frame->loader().setCurrentItem(m_currentEntry->itemForFrame(frame));
    } else if (type != FrameLoadTypeRedirectWithLockedBackForwardList) {
        m_provisionalEntry.clear();
    }

    if (type == FrameLoadTypeStandard)
        updateForStandardLoad(frame);
    else if (type == FrameLoadTypeInitialInChildFrame)
        updateForInitialLoadInChildFrame(frame);
    else
        updateWithoutCreatingNewBackForwardItem(frame);
}

static PassRefPtr<HistoryItem> itemForExport(HistoryNode* historyNode)
{
    RefPtr<HistoryItem> item = historyNode->value()->copy();
    const Vector<OwnPtr<HistoryNode> >& childEntries = historyNode->children();
    for (size_t i = 0; i < childEntries.size(); i++)
        item->addChildItem(itemForExport(childEntries[i].get()));
    return item;
}

PassRefPtr<HistoryItem> HistoryController::currentItemForExport(Frame* frame)
{
    if (!m_currentEntry)
        return 0;
    HistoryNode* historyNode = m_currentEntry->historyNodeForFrame(frame);
    return historyNode ? itemForExport(historyNode) : 0;
}

PassRefPtr<HistoryItem> HistoryController::previousItemForExport(Frame* frame)
{
    if (!m_previousEntry)
        return 0;
    HistoryNode* historyNode = m_previousEntry->historyNodeForFrame(frame);
    return historyNode ? itemForExport(historyNode) : 0;
}

PassRefPtr<HistoryItem> HistoryController::provisionalItemForExport(Frame* frame)
{
    if (!m_provisionalEntry)
        return 0;
    HistoryNode* historyNode = m_provisionalEntry->historyNodeForFrame(frame);
    return historyNode ? itemForExport(historyNode) : 0;
}

HistoryItem* HistoryController::itemForNewChildFrame(Frame* frame) const
{
    Frame* parent = frame->tree().parent();
    ASSERT(parent);
    if (!m_currentEntry || !isBackForwardLoadType(parent->loader().loadType()) || parent->document()->loadEventFinished())
        return 0;
    return m_currentEntry->itemForFrame(frame);
}

void HistoryController::initializeItem(HistoryItem* item, Frame* frame)
{
    DocumentLoader* documentLoader = frame->loader().documentLoader();
    ASSERT(documentLoader);

    KURL unreachableURL = documentLoader->unreachableURL();

    KURL url;
    KURL originalURL;

    if (!unreachableURL.isEmpty()) {
        url = unreachableURL;
        originalURL = unreachableURL;
    } else {
        url = documentLoader->url();
        originalURL = documentLoader->originalURL();
    }

    // Frames that have never successfully loaded any content
    // may have no URL at all. Currently our history code can't
    // deal with such things, so we nip that in the bud here.
    // Later we may want to learn to live with nil for URL.
    // See bug 3368236 and related bugs for more information.
    if (url.isEmpty())
        url = blankURL();
    if (originalURL.isEmpty())
        originalURL = blankURL();

    item->setURL(url);
    item->setTarget(frame->tree().uniqueName());
    item->setTargetFrameID(frame->frameID());
    item->setOriginalURLString(originalURL.string());

    // Save form state if this is a POST
    item->setFormInfoFromRequest(documentLoader->request());
}

PassRefPtr<HistoryItem> HistoryController::createItem(Frame* frame)
{
    RefPtr<HistoryItem> item = HistoryItem::create();
    initializeItem(item.get(), frame);
    frame->loader().setCurrentItem(item.get());
    return item.release();
}

void HistoryController::createItemTree(Frame* targetFrame, bool clipAtTarget)
{
    RefPtr<HistoryItem> newItem = createItem(targetFrame);
    if (!m_currentEntry) {
        m_currentEntry = HistoryEntry::create(newItem.get());
    } else {
        HistoryItem* oldItem = m_currentEntry->itemForFrame(targetFrame);
        if (!clipAtTarget && oldItem)
            newItem->setDocumentSequenceNumber(oldItem->documentSequenceNumber());
        m_previousEntry = m_currentEntry.release();
        m_currentEntry = m_previousEntry->cloneAndReplace(newItem.get(), oldItem, clipAtTarget, m_page);
    }
}

void HistoryController::createNewBackForwardItem(Frame* frame, bool doClip)
{
    // In the case of saving state about a page with frames, we store a tree of items that mirrors the frame tree.
    // The item that was the target of the user's navigation is designated as the "targetItem".
    // When this function is called with doClip=true we're able to create the whole tree except for the target's children,
    // which will be loaded in the future. That part of the tree will be filled out as the child loads are committed.
    if (!frame->loader().documentLoader()->isURLValidForNewHistoryEntry())
        return;
    createItemTree(frame, doClip);
}

void HistoryController::updateWithoutCreatingNewBackForwardItem(Frame* frame)
{
    if (!m_currentEntry || !m_currentEntry->itemForFrame(frame))
        return;

    DocumentLoader* documentLoader = frame->loader().documentLoader();

    if (!documentLoader->unreachableURL().isEmpty())
        return;

    HistoryItem* item = m_currentEntry->itemForFrame(frame);
    if (item->url() != documentLoader->url()) {
        item->reset();
        initializeItem(item, frame);
    } else {
        // Even if the final URL didn't change, the form data may have changed.
        item->setFormInfoFromRequest(documentLoader->request());
    }
}

} // namespace WebCore
