/*
 * Copyright (C) 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 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 COMEnumVariant_h
#define COMEnumVariant_h

#include <unknwn.h>

#include "COMVariantSetter.h"

template<typename ContainerType>
class COMEnumVariant final : public IEnumVARIANT {
    WTF_MAKE_NONCOPYABLE(COMEnumVariant);
public:
    static COMEnumVariant* adopt(ContainerType&);
    static COMEnumVariant* createInstance(const ContainerType&);

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

    // IEnumVARIANT
    virtual HRESULT STDMETHODCALLTYPE Next(ULONG celt, VARIANT* rgVar, ULONG* pCeltFetched);
    virtual HRESULT STDMETHODCALLTYPE Skip(ULONG celt);
    virtual HRESULT STDMETHODCALLTYPE Reset();
    virtual HRESULT STDMETHODCALLTYPE Clone(_COM_Outptr_opt_ IEnumVARIANT** ppEnum);

private:
    COMEnumVariant()
    {
    }

    COMEnumVariant(const ContainerType& container)
        : m_container(container)       
        , m_currentPos(m_container.begin())
    {
    }

    ~COMEnumVariant() {}

    ULONG m_refCount { 0 };

    ContainerType m_container;
    typename ContainerType::const_iterator m_currentPos;
};

// COMEnumVariant ------------------------------------------------------------------
template<typename ContainerType>
COMEnumVariant<ContainerType>* COMEnumVariant<ContainerType>::adopt(ContainerType& container) 
{
    COMEnumVariant* instance = new COMEnumVariant;
    instance->m_container.swap(container);
    instance->m_currentPos = instance->m_container.begin();
    instance->AddRef();
    return instance;
}

template<typename ContainerType>
COMEnumVariant<ContainerType>* COMEnumVariant<ContainerType>::createInstance(const ContainerType& container)
{
    COMEnumVariant* instance = new COMEnumVariant(container);
    instance->AddRef();
    return instance;
}

// IUnknown ------------------------------------------------------------------------
template<typename ContainerType>
HRESULT STDMETHODCALLTYPE COMEnumVariant<ContainerType>::QueryInterface(_In_ REFIID riid, _COM_Outptr_ void** ppvObject)
{
    if (!ppvObject)
        return E_POINTER;
    *ppvObject = nullptr;
    if (IsEqualGUID(riid, IID_IUnknown))
        *ppvObject = static_cast<COMEnumVariant*>(this);
    else if (IsEqualGUID(riid, IID_IEnumVARIANT))
        *ppvObject = static_cast<COMEnumVariant*>(this);
    else
        return E_NOINTERFACE;

    AddRef();
    return S_OK;
}

template<typename ContainerType>
ULONG STDMETHODCALLTYPE COMEnumVariant<ContainerType>::AddRef()
{
    return ++m_refCount;
}

template<typename ContainerType>
ULONG STDMETHODCALLTYPE COMEnumVariant<ContainerType>::Release()
{
    ULONG newRef = --m_refCount;
    if (!newRef)
        delete this;

    return newRef;
}

// IEnumVARIANT --------------------------------------------------------------------
template<typename ContainerType>
HRESULT STDMETHODCALLTYPE COMEnumVariant<ContainerType>::Next(ULONG celt, VARIANT* rgVar, ULONG* pCeltFetched)
{
    if (pCeltFetched)
        *pCeltFetched = 0;
    if (!rgVar)
        return E_POINTER;
    for (unsigned i = 0 ; i < celt; i++)
        ::VariantInit(&rgVar[i]);

    for (unsigned i = 0; i < celt; i++) {
        if (m_currentPos == m_container.end())
            return S_FALSE;

        COMVariantSetter<typename ContainerType::ValueType>::setVariant(&rgVar[i], *m_currentPos);
        ++m_currentPos;
        if (pCeltFetched)
            (*pCeltFetched)++;
    }

    return S_OK;
}

template<typename ContainerType>
HRESULT STDMETHODCALLTYPE COMEnumVariant<ContainerType>::Skip(ULONG celt) 
{
    for (unsigned i = 0; i < celt; i++) {
        if (m_currentPos == m_container.end())
            return S_FALSE;

        ++m_currentPos;
    }
    return S_OK;
}
    
template<typename ContainerType>
HRESULT STDMETHODCALLTYPE COMEnumVariant<ContainerType>::Reset() 
{
    m_currentPos = m_container.begin();
    return S_OK;
}
    
template<typename ContainerType>
HRESULT STDMETHODCALLTYPE COMEnumVariant<ContainerType>::Clone(_COM_Outptr_opt_ IEnumVARIANT** ppEnum)
{
    if (!ppEnum)
        return E_POINTER;

    *ppEnum = nullptr;
    return E_NOTIMPL;
}

#endif
