/*
 * Copyright (C) 2006, 2007 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 "COMPtr.h"
#include "WebPreferences.h"
#include "WebNotificationCenter.h"
#pragma warning(push, 0)
#include <WebCore/BString.h>
#include <WebCore/IconDatabase.h>
#include <WebCore/Image.h>
#include <WebCore/PlatformString.h>
#pragma warning(pop)
#include "shlobj.h"

using namespace WebCore;
using namespace WTF;

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

WebIconDatabase* WebIconDatabase::m_sharedWebIconDatabase = 0;

WebIconDatabase::WebIconDatabase()
: m_refCount(0)
, m_deliveryRequested(false)
{
    gClassCount++;
}

WebIconDatabase::~WebIconDatabase()
{
    gClassCount--;
}

// FIXME - <rdar://problem/4721579>
// This is code ripped directly from FileUtilities.cpp - it may be extremely useful
// to have it in a centralized location in WebKit.  But also, getting the icon database
// path should use the WebPreferences system before it falls back to some reasonable default
HRESULT userIconDatabasePath(String& path)
{
    // get the path to the user's non-roaming application data folder (Example: C:\Documents and Settings\{username}\Local Settings\Application Data\)
    TCHAR appDataPath[MAX_PATH];
    HRESULT hr = SHGetFolderPath(0, CSIDL_LOCAL_APPDATA | CSIDL_FLAG_CREATE, 0, 0, appDataPath);
    if (FAILED(hr))
        return hr;

    // make the Apple Computer and WebKit subfolder
    path = String(appDataPath) + "\\Apple Computer\\";

    WebCore::String appName = "WebKit";
    CFBundleRef bundle = CFBundleGetMainBundle();
    if (bundle) {
        CFStringRef bundleExecutable = (CFStringRef)CFBundleGetValueForInfoDictionaryKey(bundle, kCFBundleExecutableKey);
        if (bundleExecutable)
            appName = bundleExecutable;
    }
    path += appName;

    if (!CreateDirectory(path.charactersWithNullTermination(), 0)) {
        DWORD err = GetLastError();
        if (err != ERROR_ALREADY_EXISTS)
            return (HRESULT_FROM_WIN32(err));
    }

    return S_OK;
}

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);

    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())
        if (FAILED(userIconDatabasePath(databasePath)))
            LOG_ERROR("Failed to construct default icon database path");

    if (!iconDatabase()->open(databasePath))
            LOG_ERROR("Failed to open icon database path");
}

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()->iconForPageURL(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()->iconURLForPageURL(String(url, SysStringLen(url))));
    *iconURL = iconURLBSTR.release();
    return S_OK;
}

HBITMAP createDIB(LPSIZE size)
{
    HBITMAP result;

    BITMAPINFO bmInfo = {0};
    bmInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    bmInfo.bmiHeader.biWidth = size->cx;
    bmInfo.bmiHeader.biHeight = size->cy;
    bmInfo.bmiHeader.biPlanes = 1;
    bmInfo.bmiHeader.biBitCount = 32;
    bmInfo.bmiHeader.biCompression = BI_RGB;

    HDC dc = GetDC(0);
    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);
    static Image* defaultIconImage = 0;
    if (!defaultIconImage) {
        defaultIconImage = Image::loadPlatformResource("urlIcon");
    }
    m_defaultIconMap.set(*size, result);
    if (!defaultIconImage->getHBITMAPOfSize(result, size)) {
        LOG_ERROR("Failed to draw Image to HBITMAP");
        return 0;
    }
    return result;
}

// IconDatabaseClient

void WebIconDatabase::dispatchDidRemoveAllIcons()
{
    // 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::dispatchDidAddIconForPageURL(const String& pageURL)
{   
    MutexLocker locker(m_notificationMutex);
    m_notificationQueue.append(pageURL.copy());
    scheduleNotificationDelivery();
}

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

    if (!m_deliveryRequested) {
        m_deliveryRequested = true;
        callOnMainThread(WebIconDatabase::deliverNotifications);
    }
}

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()
{
    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);
    }
}
