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

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

CFDictionaryPropertyBag::CFDictionaryPropertyBag()
: m_refCount(1)
{
    gClassCount++;
    gClassNameCount.add("CFDictionaryPropertyBag");
}

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

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, __uuidof(this)))
        *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.adoptCF(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;
}