/*
 * Copyright (C) 2008, 2015 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. ``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
 * 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. 
 */

#ifndef COMPropertyBag_h
#define COMPropertyBag_h

#include <ocidl.h>
#include <unknwn.h>

#include <wtf/Noncopyable.h>
#include <wtf/HashMap.h>

#include "COMVariantSetter.h"

template<typename ValueType, typename KeyType = typename WTF::String, typename HashType = typename WTF::StringHash>
class COMPropertyBag : public IPropertyBag, public IPropertyBag2 {
    WTF_MAKE_NONCOPYABLE(COMPropertyBag);
public:
    typedef HashMap<KeyType, ValueType, HashType> HashMapType;

    static COMPropertyBag* createInstance(const HashMapType&);
    static COMPropertyBag* adopt(HashMapType&);

    // IUnknown
    virtual HRESULT STDMETHODCALLTYPE QueryInterface(_In_ REFIID riid, _COM_Outptr_ void** ppvObject);
    virtual ULONG STDMETHODCALLTYPE AddRef();
    virtual ULONG STDMETHODCALLTYPE Release();

    // IPropertyBag
    virtual HRESULT STDMETHODCALLTYPE Read(LPCOLESTR pszPropName, VARIANT*, IErrorLog*);
    virtual HRESULT STDMETHODCALLTYPE Write(_In_ LPCOLESTR pszPropName, _In_ VARIANT*);

    // IPropertyBag2
    virtual HRESULT STDMETHODCALLTYPE Read(ULONG cProperties, __inout_ecount_full(cProperties) PROPBAG2*, _In_opt_ IErrorLog*, __out_ecount_full(cProperties) VARIANT*, __inout_ecount_full_opt(cProperties) HRESULT*);
    virtual HRESULT STDMETHODCALLTYPE Write(ULONG cProperties, __inout_ecount_full(cProperties) PROPBAG2*, __inout_ecount_full(cProperties) VARIANT*);
    virtual HRESULT STDMETHODCALLTYPE CountProperties(_Out_ ULONG* pcProperties);
    virtual HRESULT STDMETHODCALLTYPE GetPropertyInfo(ULONG iProperty, ULONG cProperties, __out_ecount_full(cProperties) PROPBAG2*, _Out_ ULONG* pcProperties);
    virtual HRESULT STDMETHODCALLTYPE LoadObject(_In_ LPCOLESTR pstrName, DWORD dwHint, _In_opt_ IUnknown*, _In_opt_ IErrorLog*);

private:
    COMPropertyBag()
    {
    }

    COMPropertyBag(const HashMapType& hashMap)
        : m_hashMap(hashMap)
    {
    }

    ~COMPropertyBag() {}

    ULONG m_refCount { 0 };
    HashMapType m_hashMap;
};

// COMPropertyBag ------------------------------------------------------------------
template<typename ValueType, typename KeyType, typename HashType>
COMPropertyBag<ValueType, KeyType, HashType>* COMPropertyBag<typename ValueType, typename KeyType, HashType>::createInstance(const HashMapType& hashMap)
{
    COMPropertyBag* instance = new COMPropertyBag(hashMap);
    instance->AddRef();
    return instance;
}

template<typename ValueType, typename KeyType, typename HashType>
COMPropertyBag<ValueType, KeyType, HashType>* COMPropertyBag<typename ValueType, typename KeyType, HashType>::adopt(HashMapType& hashMap)
{
    COMPropertyBag* instance = new COMPropertyBag;
    instance->m_hashMap.swap(hashMap);
    instance->AddRef();
    return instance;
}

// IUnknown ------------------------------------------------------------------------
template<typename ValueType, typename KeyType, typename HashType>
HRESULT STDMETHODCALLTYPE COMPropertyBag<ValueType, KeyType, HashType>::QueryInterface(_In_ REFIID riid, _COM_Outptr_ void** ppvObject)
{
    if (!ppvObject)
        return E_POINTER;
    *ppvObject = nullptr;
    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_IPropertyBag2))
        *ppvObject = static_cast<IPropertyBag2*>(this);
    else
        return E_NOINTERFACE;

    AddRef();
    return S_OK;
}

template<typename ValueType, typename KeyType, typename HashType>
ULONG STDMETHODCALLTYPE COMPropertyBag<ValueType, KeyType, HashType>::AddRef()
{
    return ++m_refCount;
}

template<typename ValueType, typename KeyType, typename HashType>
ULONG STDMETHODCALLTYPE COMPropertyBag<ValueType, KeyType, HashType>::Release()
{
    ULONG newRef = --m_refCount;
    if (!newRef)
        delete this;

    return newRef;
}

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

template<typename ValueType, typename KeyType, typename HashType>
HRESULT STDMETHODCALLTYPE COMPropertyBag<ValueType, KeyType, HashType>::Read(LPCOLESTR pszPropName, VARIANT* pVar, IErrorLog* pErrorLog)
{
    if (!pszPropName)
        return E_POINTER;

    HashMapType::const_iterator it = m_hashMap.find(String(pszPropName));
    HashMapType::const_iterator end = m_hashMap.end();
    if (it == end)
        return E_INVALIDARG;

    VARTYPE requestedType = V_VT(pVar);
    V_VT(pVar) = VT_EMPTY;
    COMVariantSetter<ValueType>::setVariant(pVar, it->value);

    if (requestedType != COMVariantSetter<ValueType>::variantType(it->value) && requestedType != VT_EMPTY)
        return ::VariantChangeType(pVar, pVar, VARIANT_NOUSEROVERRIDE | VARIANT_ALPHABOOL, requestedType);

    return S_OK;
}

template<typename ValueType, typename KeyType, typename HashType>
HRESULT STDMETHODCALLTYPE COMPropertyBag<ValueType, KeyType, HashType>::Write(_In_ LPCOLESTR pszPropName, _In_ VARIANT* pVar)
{
    return E_FAIL;
}

template<typename ValueType, typename KeyType, typename HashType>
HRESULT STDMETHODCALLTYPE COMPropertyBag<ValueType, KeyType, HashType>::Read(ULONG cProperties, __inout_ecount_full(cProperties) PROPBAG2* pPropBag, _In_opt_ IErrorLog* pErrorLog, __out_ecount_full(cProperties) VARIANT* pvarValue, __inout_ecount_full_opt(cProperties) HRESULT* phrError)
{
    if (!pPropBag || !pvarValue || !phrError)
        return E_POINTER;

    HRESULT hr = S_OK;

    for (ULONG i = 0; i < cProperties; ++i) {
        ::VariantInit(&pvarValue[i]);
        pvarValue[i].vt = pPropBag[i].vt;
        phrError[i] = Read(pPropBag[i].pstrName, &pvarValue[i], pErrorLog);
        if (FAILED(phrError[i]))
            hr = E_FAIL;
    }

    return hr;
}

template<typename ValueType, typename KeyType, typename HashType>
HRESULT STDMETHODCALLTYPE COMPropertyBag<ValueType, KeyType, HashType>::Write(ULONG cProperties, __inout_ecount_full(cProperties) PROPBAG2*, __inout_ecount_full(cProperties) VARIANT*)
{
    return E_NOTIMPL;
}

template<typename ValueType, typename KeyType, typename HashType>
HRESULT STDMETHODCALLTYPE COMPropertyBag<ValueType, KeyType, HashType>::CountProperties(_Out_ ULONG* pcProperties)
{
    if (!pcProperties)
        return E_POINTER;

    *pcProperties = m_hashMap.size();
    return S_OK;
}

template<typename ValueType, typename KeyType, typename HashType>
HRESULT STDMETHODCALLTYPE COMPropertyBag<ValueType, KeyType, HashType>::GetPropertyInfo(ULONG iProperty, ULONG cProperties, __out_ecount_full(cProperties) PROPBAG2* pPropBag, _Out_ ULONG* pcProperties)
{
    if (!pPropBag || !pcProperties)
        return E_POINTER;

    *pcProperties = 0;

    if (m_hashMap.size() <= iProperty)
        return E_INVALIDARG;

    *pcProperties = 0;
    typedef HashMapType::const_iterator Iterator;
    Iterator current = m_hashMap.begin();
    Iterator end = m_hashMap.end();
    for (ULONG i = 0; i < iProperty; ++i, ++current)
        ;
    for (ULONG j = 0; j < cProperties && current != end; ++j, ++current) {
        // FIXME: the following fields aren't filled in
        //pPropBag[j].cfType;   // (CLIPFORMAT) Clipboard format or MIME type of the property.
        //pPropBag[j].clsid;    // (CLSID) CLSID of the object. This member is valid only if dwType is PROPBAG2_TYPE_OBJECT.

        pPropBag[j].dwType = PROPBAG2_TYPE_DATA;
        pPropBag[j].vt = COMVariantSetter<ValueType>::variantType(current->value);
        pPropBag[j].dwHint = iProperty + j;
        pPropBag[j].pstrName = (LPOLESTR)CoTaskMemAlloc(sizeof(wchar_t)*(current->key.length()+1));
        if (!pPropBag[j].pstrName)
            return E_OUTOFMEMORY;
        wcscpy_s(pPropBag[j].pstrName, current->key.length()+1, static_cast<String>(current->key).charactersWithNullTermination().data());
        ++*pcProperties;
    }
    return S_OK;
}

template<typename ValueType, typename KeyType, typename HashType>
HRESULT STDMETHODCALLTYPE COMPropertyBag<ValueType, KeyType, HashType>::LoadObject(_In_ LPCOLESTR pstrName, DWORD dwHint, _In_opt_ IUnknown*, _In_opt_ IErrorLog*)
{
    return E_NOTIMPL;
}

#endif // COMPropertyBag_h
