/*
 * 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 "CFDictionaryPropertyBag.h"

#include "MarshallingHelpers.h"

#include <initguid.h>
// {675E712B-8253-4121-A1F0-6A804D095668}
DEFINE_GUID(IID_CFDictionaryPropertyBag, 0x675e712b, 0x8253, 0x4121, 0xa1, 0xf0, 0x6a, 0x80, 0x4d, 0x9, 0x56, 0x68);

// CFDictionaryPropertyBag -----------------------------------------------

CFDictionaryPropertyBag::CFDictionaryPropertyBag()
: m_refCount(1)
{
}

CFDictionaryPropertyBag* CFDictionaryPropertyBag::createInstance()
{
    CFDictionaryPropertyBag* instance = new CFDictionaryPropertyBag();
    return instance;
}

void CFDictionaryPropertyBag::setDictionary(CFMutableDictionaryRef dictionary)
{
    m_dictionary = dictionary;
}

CFMutableDictionaryRef CFDictionaryPropertyBag::dictionary() const
{
    return m_dictionary.get();
}

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

HRESULT STDMETHODCALLTYPE CFDictionaryPropertyBag::QueryInterface(REFIID riid, void** ppvObject)
{
    *ppvObject = 0;
    if (IsEqualGUID(riid, IID_IUnknown))
        *ppvObject = static_cast<IPropertyBag*>(this);
    else if (IsEqualGUID(riid, IID_IPropertyBag))
        *ppvObject = static_cast<IPropertyBag*>(this);
    else if (IsEqualGUID(riid, IID_CFDictionaryPropertyBag))
        *ppvObject = this;
    else
        return E_NOINTERFACE;

    AddRef();
    return S_OK;
}

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

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

    return newRef;
}

// IPropertyBag ------------------------------------------------------------

static bool ConvertCFTypeToVariant(VARIANT* pVar, void* cfObj)
{
    if (!cfObj) {
        V_VT(pVar) = VT_NULL;
        return true;
    }
    else {
        // if caller expects a string, retrieve BSTR from CFStringRef
        if (V_VT(pVar) == VT_BSTR) {
            V_BSTR(pVar) = MarshallingHelpers::CFStringRefToBSTR((CFStringRef) cfObj);
            return true;
        } else if (V_VT(pVar) == VT_I4) {
            V_I4(pVar) = MarshallingHelpers::CFNumberRefToInt((CFNumberRef) cfObj);
            return true;
        } else if (!!(V_VT(pVar)&VT_ARRAY)) {
            if ((V_VT(pVar)&~VT_ARRAY) == VT_BSTR) {
                V_ARRAY(pVar) = MarshallingHelpers::stringArrayToSafeArray((CFArrayRef) cfObj);
                return true;
            } else if ((V_VT(pVar)&~VT_ARRAY) == VT_I4) {
                V_ARRAY(pVar) = MarshallingHelpers::intArrayToSafeArray((CFArrayRef) cfObj);
                return true;
            } else if ((V_VT(pVar)&~VT_ARRAY) == VT_UNKNOWN) {
                V_ARRAY(pVar) = MarshallingHelpers::iunknownArrayToSafeArray((CFArrayRef) cfObj);
                return true;
            }
        }
    }
    return false;
}

static bool ConvertVariantToCFType(VARIANT* pVar, void** cfObj)
{
    if (V_VT(pVar) == VT_NULL) {
        *cfObj = 0;
        return true;
    }
    else {
        // if caller expects a string, retrieve BSTR from CFStringRef
        if (V_VT(pVar) == VT_BSTR) {
            *cfObj = (void*) MarshallingHelpers::BSTRToCFStringRef(V_BSTR(pVar));
            return true;
        } else if (V_VT(pVar) == VT_I4) {
            *cfObj = (void*) MarshallingHelpers::intToCFNumberRef(V_I4(pVar));
            return true;
        } else if (!!(V_VT(pVar)&VT_ARRAY)) {
            if ((V_VT(pVar)&~VT_ARRAY) == VT_BSTR) {
                *cfObj = (void*) MarshallingHelpers::safeArrayToStringArray(V_ARRAY(pVar));
                return true;
            } else if ((V_VT(pVar)&~VT_ARRAY) == VT_I4) {
                *cfObj = (void*) MarshallingHelpers::safeArrayToIntArray(V_ARRAY(pVar));
                return true;
            } else if ((V_VT(pVar)&~VT_ARRAY) == VT_UNKNOWN) {
                *cfObj = (void*) MarshallingHelpers::safeArrayToIUnknownArray(V_ARRAY(pVar));
                return true;
            }
        }
    }
    return false;
}

HRESULT STDMETHODCALLTYPE CFDictionaryPropertyBag::Read(LPCOLESTR pszPropName, VARIANT *pVar, IErrorLog * /*pErrorLog*/)
{
    if (!pszPropName)
        return E_POINTER;
    if (m_dictionary) {
        void* value;
        CFStringRef key = MarshallingHelpers::LPCOLESTRToCFStringRef(pszPropName);
        HRESULT hr = E_FAIL;
        if (CFDictionaryGetValueIfPresent(m_dictionary.get(), key, (const void**) &value)) {
            if (ConvertCFTypeToVariant(pVar, value))
                hr = S_OK;
        } else
            hr = E_INVALIDARG;
        CFRelease(key);
        return hr;
    }
    return E_FAIL;
}
        
HRESULT STDMETHODCALLTYPE CFDictionaryPropertyBag::Write(LPCOLESTR pszPropName, VARIANT* pVar)
{
    if (!pszPropName || !pVar)
        return E_POINTER;
    if (!m_dictionary) {
        m_dictionary = CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
    }
    void* cfObj;
    if (ConvertVariantToCFType(pVar, &cfObj)) {
        CFStringRef key = MarshallingHelpers::LPCOLESTRToCFStringRef(pszPropName);
        CFDictionaryAddValue(m_dictionary.get(), key, cfObj);
        // CFDictionaryAddValue should automatically retain the CF objects passed in, so release them here
        CFRelease(key);
        CFRelease(cfObj);
        return S_OK;
    }
    return E_FAIL;
}