/*
 * Copyright (C) 2006, 2007, 2008, 2009 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 COMPUTER, INC. ``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 COMPUTER, INC. OR
 * 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 "WebKitDLL.h"
#include "WebIconDatabase.h"

#include "CFDictionaryPropertyBag.h"
#include "WebPreferences.h"
#include "WebNotificationCenter.h"
#include <WebCore/BitmapInfo.h>
#include <WebCore/BString.h>
#include <WebCore/COMPtr.h>
#include <WebCore/FileSystem.h>
#include <WebCore/IconDatabase.h>
#include <WebCore/Image.h>
#include <WebCore/PlatformString.h>
#include <WebCore/SharedBuffer.h>
#include <wtf/MainThread.h>
#include "shlobj.h"

using namespace WebCore;
using namespace WTF;

// WebIconDatabase ----------------------------------------------------------------

WebIconDatabase* WebIconDatabase::m_sharedWebIconDatabase = 0;

WebIconDatabase::WebIconDatabase()
: m_refCount(0)
, m_deliveryRequested(false)
{
    gClassCount++;
    gClassNameCount.add("WebIconDatabase");
}

WebIconDatabase::~WebIconDatabase()
{
    gClassCount--;
    gClassNameCount.remove("WebIconDatabase");
}

void WebIconDatabase::init()
{
    WebPreferences* standardPrefs = WebPreferences::sharedStandardPreferences();
    BOOL enabled = FALSE;
    if (FAILED(standardPrefs->iconDatabaseEnabled(&enabled))) {
        enabled = FALSE;
        LOG_ERROR("Unable to get icon database enabled preference");
    }
    iconDatabase().setEnabled(!!enabled);
    if (!(!!enabled))
        return;

    startUpIconDatabase();
}

void WebIconDatabase::startUpIconDatabase()
{
    WebPreferences* standardPrefs = WebPreferences::sharedStandardPreferences();

    iconDatabase().setClient(this);

    BSTR prefDatabasePath = 0;
    if (FAILED(standardPrefs->iconDatabaseLocation(&prefDatabasePath)))
        LOG_ERROR("Unable to get icon database location preference");

    String databasePath(prefDatabasePath, SysStringLen(prefDatabasePath));
    SysFreeString(prefDatabasePath);

    if (databasePath.isEmpty()) {
        databasePath = localUserSpecificStorageDirectory();
        if (databasePath.isEmpty())
            LOG_ERROR("Failed to construct default icon database path");
    }

    if (!iconDatabase().open(databasePath, WebCore::IconDatabase::defaultDatabaseFilename()))
            LOG_ERROR("Failed to open icon database path");
}

void WebIconDatabase::shutDownIconDatabase()
{
}

WebIconDatabase* WebIconDatabase::createInstance()
{
    WebIconDatabase* instance = new WebIconDatabase();
    instance->AddRef();
    return instance;
}

WebIconDatabase* WebIconDatabase::sharedWebIconDatabase()
{
    if (m_sharedWebIconDatabase) {
        m_sharedWebIconDatabase->AddRef();
        return m_sharedWebIconDatabase;
    }
    m_sharedWebIconDatabase = createInstance();
    m_sharedWebIconDatabase->init();
    return m_sharedWebIconDatabase;
}

// IUnknown -------------------------------------------------------------------

HRESULT STDMETHODCALLTYPE WebIconDatabase::QueryInterface(REFIID riid, void** ppvObject)
{
    *ppvObject = 0;
    if (IsEqualGUID(riid, IID_IUnknown))
        *ppvObject = static_cast<IWebIconDatabase*>(this);
    else if (IsEqualGUID(riid, IID_IWebIconDatabase))
        *ppvObject = static_cast<IWebIconDatabase*>(this);
    else
        return E_NOINTERFACE;

    AddRef();
    return S_OK;
}

ULONG STDMETHODCALLTYPE WebIconDatabase::AddRef(void)
{
    return ++m_refCount;
}

ULONG STDMETHODCALLTYPE WebIconDatabase::Release(void)
{
    ULONG newRef = --m_refCount;
    if (!newRef)
        delete(this);

    return newRef;
}

// IWebIconDatabase --------------------------------------------------------------------

HRESULT STDMETHODCALLTYPE WebIconDatabase::sharedIconDatabase(
        /* [retval][out] */ IWebIconDatabase** result)
{
    *result = sharedWebIconDatabase();
    return S_OK;
}

HRESULT STDMETHODCALLTYPE WebIconDatabase::iconForURL(
        /* [in] */ BSTR url,
        /* [optional][in] */ LPSIZE size,
        /* [optional][in] */ BOOL /*cache*/,
        /* [retval][out] */ OLE_HANDLE* bitmap)
{
    IntSize intSize(*size);

    Image* icon = 0;
    if (url)
        icon = iconDatabase().synchronousIconForPageURL(String(url, SysStringLen(url)), intSize);

    // Make sure we check for the case of an "empty image"
    if (icon && icon->width()) {
        *bitmap = (OLE_HANDLE)(ULONG64)getOrCreateSharedBitmap(size);
        if (!icon->getHBITMAPOfSize((HBITMAP)(ULONG64)*bitmap, size)) {
            LOG_ERROR("Failed to draw Image to HBITMAP");
            *bitmap = 0;
            return E_FAIL;
        }
        return S_OK;
    }

    return defaultIconWithSize(size, bitmap);
}

HRESULT STDMETHODCALLTYPE WebIconDatabase::defaultIconWithSize(
        /* [in] */ LPSIZE size,
        /* [retval][out] */ OLE_HANDLE* result)
{
    *result = (OLE_HANDLE)(ULONG64)getOrCreateDefaultIconBitmap(size);
    return S_OK;
}

HRESULT STDMETHODCALLTYPE WebIconDatabase::retainIconForURL(
        /* [in] */ BSTR url)
{
    iconDatabase().retainIconForPageURL(String(url, SysStringLen(url)));
    return S_OK;
}

HRESULT STDMETHODCALLTYPE WebIconDatabase::releaseIconForURL(
        /* [in] */ BSTR url)
{
    iconDatabase().releaseIconForPageURL(String(url, SysStringLen(url)));
    return S_OK;
}

HRESULT STDMETHODCALLTYPE WebIconDatabase::removeAllIcons(void)
{
    iconDatabase().removeAllIcons();
    return S_OK;
}

HRESULT STDMETHODCALLTYPE WebIconDatabase::delayDatabaseCleanup(void)
{
    IconDatabase::delayDatabaseCleanup();
    return S_OK;
}

HRESULT STDMETHODCALLTYPE WebIconDatabase::allowDatabaseCleanup(void)
{
    IconDatabase::allowDatabaseCleanup();
    return S_OK;
}

HRESULT STDMETHODCALLTYPE WebIconDatabase::iconURLForURL( 
        /* [in] */ BSTR url,
        /* [retval][out] */ BSTR* iconURL)
{
    if (!url || !iconURL)
        return E_POINTER;
    BString iconURLBSTR(iconDatabase().synchronousIconURLForPageURL(String(url, SysStringLen(url))));
    *iconURL = iconURLBSTR.release();
    return S_OK;
}

HRESULT STDMETHODCALLTYPE WebIconDatabase::isEnabled( 
        /* [retval][out] */ BOOL *result)
{
    *result = iconDatabase().isEnabled();
    return S_OK;
}

HRESULT STDMETHODCALLTYPE WebIconDatabase::setEnabled( 
        /* [in] */ BOOL flag)
{
    BOOL currentlyEnabled;
    isEnabled(&currentlyEnabled);
    if (currentlyEnabled && !flag) {
        iconDatabase().setEnabled(false);
        shutDownIconDatabase();
    } else if (!currentlyEnabled && flag) {
        iconDatabase().setEnabled(true);
        startUpIconDatabase();
    }
    return S_OK;
}

HRESULT STDMETHODCALLTYPE WebIconDatabase::hasIconForURL(
        /* [in] */ BSTR url,
        /* [out][retval] */ BOOL* result)
{
    if (!url || !result)
        return E_POINTER;

    String urlString(url, SysStringLen(url));

    // Passing a size parameter of 0, 0 means we don't care about the result of the image, we just
    // want to make sure the read from disk to load the icon is kicked off.
    iconDatabase().synchronousIconForPageURL(urlString, IntSize(0, 0));

    // Check to see if we have a non-empty icon URL for the page, and if we do, we have an icon for
    // the page.
    *result = !(iconDatabase().synchronousIconURLForPageURL(urlString).isEmpty());

    return S_OK;
}

HBITMAP createDIB(LPSIZE size)
{
    BitmapInfo bmInfo = BitmapInfo::create(IntSize(*size));

    HDC dc = GetDC(0);
    HBITMAP result = CreateDIBSection(dc, &bmInfo, DIB_RGB_COLORS, 0, 0, 0);
    ReleaseDC(0, dc);

    return result;
}

HBITMAP WebIconDatabase::getOrCreateSharedBitmap(LPSIZE size)
{
    HBITMAP result = m_sharedIconMap.get(*size);
    if (result)
        return result;
    result = createDIB(size);
    m_sharedIconMap.set(*size, result);
    return result;
}

HBITMAP WebIconDatabase::getOrCreateDefaultIconBitmap(LPSIZE size)
{
    HBITMAP result = m_defaultIconMap.get(*size);
    if (result)
        return result;

    result = createDIB(size);

    m_defaultIconMap.set(*size, result);
    if (!iconDatabase().defaultIcon(*size)->getHBITMAPOfSize(result, size)) {
        LOG_ERROR("Failed to draw Image to HBITMAP");
        return 0;
    }
    return result;
}

// IconDatabaseClient

bool WebIconDatabase::performImport()
{
    // Windows doesn't do any old-style database importing.
    return true;
}

void WebIconDatabase::didRemoveAllIcons()
{
    // Queueing the empty string is a special way of saying "this queued notification is the didRemoveAllIcons notification"
    MutexLocker locker(m_notificationMutex);
    m_notificationQueue.append(String());
    scheduleNotificationDelivery();
}

void WebIconDatabase::didImportIconURLForPageURL(const WTF::String& pageURL)
{
    MutexLocker locker(m_notificationMutex);
    m_notificationQueue.append(pageURL.threadsafeCopy());
    scheduleNotificationDelivery();
}

void WebIconDatabase::didImportIconDataForPageURL(const WTF::String& pageURL)
{
    // WebKit1 only has a single "icon did change" notification.
    didImportIconURLForPageURL(pageURL);
}

void WebIconDatabase::didChangeIconForPageURL(const WTF::String& pageURL)
{
    // WebKit1 only has a single "icon did change" notification.
    didImportIconURLForPageURL(pageURL);
}

void WebIconDatabase::didFinishURLImport()
{
}

void WebIconDatabase::scheduleNotificationDelivery()
{
    // Caller of this method must hold the m_notificationQueue lock
    ASSERT(!m_notificationMutex.tryLock());

    if (!m_deliveryRequested) {
        m_deliveryRequested = true;
        callOnMainThread(deliverNotifications, 0);
    }
}

BSTR WebIconDatabase::iconDatabaseDidAddIconNotification()
{
    static BSTR didAddIconName = SysAllocString(WebIconDatabaseDidAddIconNotification);
    return didAddIconName;
}

CFStringRef WebIconDatabase::iconDatabaseNotificationUserInfoURLKey()
{
    static CFStringRef iconUserInfoURLKey = String(WebIconNotificationUserInfoURLKey).createCFString();
    return iconUserInfoURLKey;
}

BSTR WebIconDatabase::iconDatabaseDidRemoveAllIconsNotification()
{
    static BSTR didRemoveAllIconsName = SysAllocString(WebIconDatabaseDidRemoveAllIconsNotification);
    return didRemoveAllIconsName;
}

static void postDidRemoveAllIconsNotification(WebIconDatabase* iconDB)
{
    IWebNotificationCenter* notifyCenter = WebNotificationCenter::defaultCenterInternal();
    notifyCenter->postNotificationName(WebIconDatabase::iconDatabaseDidRemoveAllIconsNotification(), static_cast<IWebIconDatabase*>(iconDB), 0);
}

static void postDidAddIconNotification(const String& pageURL, WebIconDatabase* iconDB)
{
    RetainPtr<CFMutableDictionaryRef> dictionary(AdoptCF, 
    CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));

    RetainPtr<CFStringRef> url(AdoptCF, pageURL.createCFString());
    CFDictionaryAddValue(dictionary.get(), WebIconDatabase::iconDatabaseNotificationUserInfoURLKey(), url.get());

    COMPtr<CFDictionaryPropertyBag> userInfo = CFDictionaryPropertyBag::createInstance();
    userInfo->setDictionary(dictionary.get());

    IWebNotificationCenter* notifyCenter = WebNotificationCenter::defaultCenterInternal();
    notifyCenter->postNotificationName(WebIconDatabase::iconDatabaseDidAddIconNotification(), static_cast<IWebIconDatabase*>(iconDB), userInfo.get());
}

void WebIconDatabase::deliverNotifications(void*)
{
    ASSERT(m_sharedWebIconDatabase);
    if (!m_sharedWebIconDatabase)
        return;

    ASSERT(m_sharedWebIconDatabase->m_deliveryRequested);

    Vector<String> queue;
    {
        MutexLocker locker(m_sharedWebIconDatabase->m_notificationMutex);
        queue.swap(m_sharedWebIconDatabase->m_notificationQueue);
        m_sharedWebIconDatabase->m_deliveryRequested = false;
    }

    for (unsigned i = 0; i < queue.size(); ++i) {
        if (queue[i].isNull())
            postDidRemoveAllIconsNotification(m_sharedWebIconDatabase);
        else
            postDidAddIconNotification(queue[i], m_sharedWebIconDatabase);
    }
}
