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

#include "DataReference.h"
#include "Logging.h"
#include "WebContext.h"
#include "WebIconDatabaseProxyMessages.h"
#include <WebCore/FileSystem.h>
#include <WebCore/IconDatabase.h>
#include <WebCore/IconDatabaseBase.h>
#include <wtf/text/CString.h>
#include <wtf/text/WTFString.h>

using namespace WebCore;

namespace WebKit {

PassRefPtr<WebIconDatabase> WebIconDatabase::create(WebContext* context)
{
    return adoptRef(new WebIconDatabase(context));
}

WebIconDatabase::~WebIconDatabase()
{
}

WebIconDatabase::WebIconDatabase(WebContext* context)
    : m_webContext(context)
    , m_urlImportCompleted(false)
    , m_databaseCleanupDisabled(false)
{
}

void WebIconDatabase::invalidate()
{
}

void WebIconDatabase::setDatabasePath(const String& path)
{
    if (isOpen()) {
        LOG_ERROR("Icon database already has a path and is already open. We don't currently support changing its path and reopening.");
        return;
    }

    m_iconDatabaseImpl =  IconDatabase::create();
    m_iconDatabaseImpl->setClient(this);
    IconDatabase::delayDatabaseCleanup();
    m_databaseCleanupDisabled = true;
    m_iconDatabaseImpl->setEnabled(true);
    if (!m_iconDatabaseImpl->open(directoryName(path), pathGetFileName(path))) {
        LOG_ERROR("Unable to open WebKit2 icon database on disk");
        m_iconDatabaseImpl.clear();
        setGlobalIconDatabase(0);
        IconDatabase::allowDatabaseCleanup();
        m_databaseCleanupDisabled = false;
    }
    setGlobalIconDatabase(m_iconDatabaseImpl.get());
}

void WebIconDatabase::enableDatabaseCleanup()
{
    if (!m_iconDatabaseImpl) {
        LOG_ERROR("Cannot enabled Icon Database cleanup - it hasn't been opened yet.");
        return;
    }

    if (!m_databaseCleanupDisabled) {
        LOG_ERROR("Attempt to enable database cleanup, but it's already enabled.");
        ASSERT_NOT_REACHED();
        return;
    }
    
    IconDatabase::allowDatabaseCleanup();
    m_databaseCleanupDisabled = false;
}

void WebIconDatabase::retainIconForPageURL(const String& pageURL)
{
    if (m_iconDatabaseImpl)
        m_iconDatabaseImpl->retainIconForPageURL(pageURL);
}

void WebIconDatabase::releaseIconForPageURL(const String& pageURL)
{
    if (m_iconDatabaseImpl)
        m_iconDatabaseImpl->releaseIconForPageURL(pageURL);
}

void WebIconDatabase::setIconURLForPageURL(const String& iconURL, const String& pageURL)
{
    LOG(IconDatabase, "WK2 UIProcess setting icon URL %s for page URL %s", iconURL.ascii().data(), pageURL.ascii().data());
    if (m_iconDatabaseImpl)
        m_iconDatabaseImpl->setIconURLForPageURL(iconURL, pageURL);
}

void WebIconDatabase::setIconDataForIconURL(const CoreIPC::DataReference& iconData, const String& iconURL)
{
    LOG(IconDatabase, "WK2 UIProcess setting icon data (%i bytes) for page URL %s", (int)iconData.size(), iconURL.ascii().data());
    if (!m_iconDatabaseImpl)
        return;

    RefPtr<SharedBuffer> buffer = SharedBuffer::create(iconData.data(), iconData.size());
    m_iconDatabaseImpl->setIconDataForIconURL(buffer.release(), iconURL);
}

void WebIconDatabase::synchronousIconDataForPageURL(const String&, CoreIPC::DataReference& iconData)
{
    iconData = CoreIPC::DataReference();
}

void WebIconDatabase::synchronousIconURLForPageURL(const String& pageURL, String& iconURL)
{
    if (!m_iconDatabaseImpl) {
        iconURL = String();
        return;
    }

    iconURL = m_iconDatabaseImpl->synchronousIconURLForPageURL(pageURL);
}

void WebIconDatabase::synchronousIconDataKnownForIconURL(const String&, bool& iconDataKnown) const
{
    iconDataKnown = false;
}

void WebIconDatabase::synchronousLoadDecisionForIconURL(const String&, int& loadDecision) const
{
    loadDecision = static_cast<int>(IconLoadNo);
}

void WebIconDatabase::getLoadDecisionForIconURL(const String& iconURL, uint64_t callbackID)
{
    LOG(IconDatabase, "WK2 UIProcess getting load decision for icon URL %s with callback ID %lli", iconURL.ascii().data(), static_cast<long long>(callbackID));

    if (!m_webContext)
        return;

    if (!m_iconDatabaseImpl || !m_iconDatabaseImpl->isOpen() || iconURL.isEmpty()) {
        // FIXME (Multi-WebProcess): <rdar://problem/12240223> We need to know which connection to send this message to.
        m_webContext->sendToAllProcesses(Messages::WebIconDatabaseProxy::ReceivedIconLoadDecision(static_cast<int>(IconLoadNo), callbackID));
        return;
    }
    
    // If the decision hasn't been read from disk yet, set this url and callback ID aside to be notifed later
    IconLoadDecision decision = m_iconDatabaseImpl->synchronousLoadDecisionForIconURL(iconURL, 0);
    if (decision == IconLoadUnknown) {
        // We should never get an unknown load decision after the URL import has completed.
        ASSERT(!m_urlImportCompleted);
        
        m_pendingLoadDecisionURLMap.set(callbackID, iconURL);
        return;    
    }

    // FIXME (Multi-WebProcess): <rdar://problem/12240223> We need to know which connection to send this message to.
    m_webContext->sendToAllProcesses(Messages::WebIconDatabaseProxy::ReceivedIconLoadDecision((int)decision, callbackID));
}

void WebIconDatabase::didReceiveIconForPageURL(const String& pageURL)
{
    notifyIconDataReadyForPageURL(pageURL);
}

Image* WebIconDatabase::imageForPageURL(const String& pageURL, const WebCore::IntSize& iconSize)
{
    if (!m_webContext || !m_iconDatabaseImpl || !m_iconDatabaseImpl->isOpen() || pageURL.isEmpty())
        return 0;    

    // The WebCore IconDatabase ignores the passed in size parameter.
    // If that changes we'll need to rethink how this API is exposed.
    return m_iconDatabaseImpl->synchronousIconForPageURL(pageURL, iconSize);
}

WebCore::NativeImagePtr WebIconDatabase::nativeImageForPageURL(const String& pageURL, const WebCore::IntSize& iconSize)
{
    if (!m_webContext || !m_iconDatabaseImpl || !m_iconDatabaseImpl->isOpen() || pageURL.isEmpty())
        return 0;

    return m_iconDatabaseImpl->synchronousNativeIconForPageURL(pageURL, iconSize);
}

bool WebIconDatabase::isOpen()
{
    return m_iconDatabaseImpl && m_iconDatabaseImpl->isOpen();
}

bool WebIconDatabase::isUrlImportCompleted()
{
    return m_urlImportCompleted;
}

void WebIconDatabase::removeAllIcons()
{
    m_iconDatabaseImpl->removeAllIcons();   
}

void WebIconDatabase::checkIntegrityBeforeOpening()
{
    IconDatabase::checkIntegrityBeforeOpening();
}

void WebIconDatabase::close()
{
    m_iconDatabaseImpl->close();
}

void WebIconDatabase::initializeIconDatabaseClient(const WKIconDatabaseClient* client)
{
    m_iconDatabaseClient.initialize(client);
}

// WebCore::IconDatabaseClient

void WebIconDatabase::didImportIconURLForPageURL(const String& pageURL)
{
    didChangeIconForPageURL(pageURL);
}

void WebIconDatabase::didImportIconDataForPageURL(const String& pageURL)
{
    notifyIconDataReadyForPageURL(pageURL);
}

void WebIconDatabase::didChangeIconForPageURL(const String& pageURL)
{
    m_iconDatabaseClient.didChangeIconForPageURL(this, WebURL::create(pageURL).get());
}

void WebIconDatabase::didRemoveAllIcons()
{
    m_iconDatabaseClient.didRemoveAllIcons(this);
}

void WebIconDatabase::didFinishURLImport()
{
    if (!m_webContext)
        return;
    
    ASSERT(!m_urlImportCompleted);

    LOG(IconDatabase, "WK2 UIProcess URL import complete, notifying all %i pending page URL load decisions", m_pendingLoadDecisionURLMap.size());

    HashMap<uint64_t, String>::iterator i = m_pendingLoadDecisionURLMap.begin();
    HashMap<uint64_t, String>::iterator end = m_pendingLoadDecisionURLMap.end();
    
    for (; i != end; ++i) {
        LOG(IconDatabase, "WK2 UIProcess performing delayed callback on callback ID %i for page url %s", (int)i->first, i->second.ascii().data());
        IconLoadDecision decision = m_iconDatabaseImpl->synchronousLoadDecisionForIconURL(i->second, 0);

        // Decisions should never be unknown after the inital import is complete
        ASSERT(decision != IconLoadUnknown);

        // FIXME (Multi-WebProcess): <rdar://problem/12240223> We need to know which connection to send this message to.
        m_webContext->sendToAllProcesses(Messages::WebIconDatabaseProxy::ReceivedIconLoadDecision(static_cast<int>(decision), i->first));
    }
    
    m_pendingLoadDecisionURLMap.clear();
    
    m_urlImportCompleted = true;
}

void WebIconDatabase::didReceiveMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* decoder)
{
    didReceiveWebIconDatabaseMessage(connection, messageID, decoder);
}

void WebIconDatabase::didReceiveSyncMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* decoder, OwnPtr<CoreIPC::ArgumentEncoder>& reply)
{
    didReceiveSyncWebIconDatabaseMessage(connection, messageID, decoder, reply);
}

void WebIconDatabase::notifyIconDataReadyForPageURL(const String& pageURL)
{
    m_iconDatabaseClient.iconDataReadyForPageURL(this, WebURL::create(pageURL).get());
    didChangeIconForPageURL(pageURL);
}

} // namespace WebKit
