/*
 * Implementation of IEnumFilters Interface
 *
 * Copyright 2004 Christian Costa
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include "quartz_private.h"

#include "wine/debug.h"

WINE_DEFAULT_DEBUG_CHANNEL(quartz);

typedef struct IEnumFiltersImpl
{
    const IEnumFiltersVtbl * lpVtbl;
    ULONG refCount;
    IBaseFilter ** ppFilters;
    int nFilters;
    ULONG uIndex;
} IEnumFiltersImpl;

static const struct IEnumFiltersVtbl IEnumFiltersImpl_Vtbl;

HRESULT IEnumFiltersImpl_Construct(IBaseFilter ** ppFilters, ULONG nFilters, IEnumFilters ** ppEnum)
{
    /* Note: The incoming IBaseFilter interfaces are not AddRef'd here as in Windows,
     * they should have been previously AddRef'd. */
    IEnumFiltersImpl * pEnumFilters = CoTaskMemAlloc(sizeof(IEnumFiltersImpl));

    TRACE("(%p, %ld, %p)\n", ppFilters, nFilters, ppEnum);

    *ppEnum = NULL;

    if (!pEnumFilters)
    {
        return E_OUTOFMEMORY;
    }

    pEnumFilters->lpVtbl = &IEnumFiltersImpl_Vtbl;
    pEnumFilters->refCount = 1;
    pEnumFilters->uIndex = 0;
    pEnumFilters->nFilters = nFilters;
    pEnumFilters->ppFilters = CoTaskMemAlloc(sizeof(IBaseFilter*) * nFilters);
    if (!pEnumFilters->ppFilters)
    {
	CoTaskMemFree(pEnumFilters);
	return E_OUTOFMEMORY;
    }

    memcpy(pEnumFilters->ppFilters, ppFilters, nFilters * sizeof(IBaseFilter*));

    *ppEnum = (IEnumFilters *)(&pEnumFilters->lpVtbl);
    return S_OK;
}

static HRESULT WINAPI IEnumFiltersImpl_QueryInterface(IEnumFilters * iface, REFIID riid, LPVOID * ppv)
{
    TRACE("(%p)->(%s, %p)\n", iface, qzdebugstr_guid(riid), ppv);

    *ppv = NULL;

    if (IsEqualIID(riid, &IID_IUnknown))
        *ppv = (LPVOID)iface;
    else if (IsEqualIID(riid, &IID_IEnumFilters))
        *ppv = (LPVOID)iface;

    if (*ppv)
    {
        IUnknown_AddRef((IUnknown *)(*ppv));
        return S_OK;
    }

    FIXME("No interface for %s!\n", qzdebugstr_guid(riid));

    return E_NOINTERFACE;
}

static ULONG WINAPI IEnumFiltersImpl_AddRef(IEnumFilters * iface)
{
    IEnumFiltersImpl *This = (IEnumFiltersImpl *)iface;
    TRACE("(%p)->()\n", iface);
    return ++This->refCount;
}

static ULONG WINAPI IEnumFiltersImpl_Release(IEnumFilters * iface)
{
    IEnumFiltersImpl *This = (IEnumFiltersImpl *)iface;
    TRACE("(%p)->()\n", iface);
    if (!--This->refCount)
    {
        CoTaskMemFree(This->ppFilters);
        CoTaskMemFree(This);
        return 0;
    }
    else
        return This->refCount;
}

static HRESULT WINAPI IEnumFiltersImpl_Next(IEnumFilters * iface, ULONG cFilters, IBaseFilter ** ppFilters, ULONG * pcFetched)
{
    ULONG cFetched; 
    ULONG i;
    IEnumFiltersImpl *This = (IEnumFiltersImpl *)iface;

    cFetched = min(This->nFilters, This->uIndex + cFilters) - This->uIndex;

    TRACE("(%p)->(%lu, %p, %p)\n", iface, cFilters, ppFilters, pcFetched);

    for (i = 0; i < cFetched; i++)
    {
	ppFilters[i] = This->ppFilters[This->uIndex + i];
	IBaseFilter_AddRef(ppFilters[i]);
    }

    This->uIndex += cFetched;

    if (pcFetched)
        *pcFetched = cFetched;

    if (cFetched != cFilters)
        return S_FALSE;
    return S_OK;
}

static HRESULT WINAPI IEnumFiltersImpl_Skip(IEnumFilters * iface, ULONG cFilters)
{
    IEnumFiltersImpl *This = (IEnumFiltersImpl *)iface;

    TRACE("(%p)->(%lu)\n", iface, cFilters);

    if (This->uIndex + cFilters < This->nFilters)
    {
        This->uIndex += cFilters;
        return S_OK;
    }
    return S_FALSE;
}

static HRESULT WINAPI IEnumFiltersImpl_Reset(IEnumFilters * iface)
{
    IEnumFiltersImpl *This = (IEnumFiltersImpl *)iface;

    TRACE("(%p)->()\n", iface);

    This->uIndex = 0;
    return S_OK;
}

static HRESULT WINAPI IEnumFiltersImpl_Clone(IEnumFilters * iface, IEnumFilters ** ppEnum)
{
    HRESULT hr;
    IEnumFiltersImpl *This = (IEnumFiltersImpl *)iface;

    TRACE("(%p)->(%p)\n", iface, ppEnum);

    hr = IEnumFiltersImpl_Construct(This->ppFilters, This->nFilters, ppEnum);
    if (FAILED(hr))
        return hr;
    return IEnumFilters_Skip(*ppEnum, This->uIndex);
}

static const IEnumFiltersVtbl IEnumFiltersImpl_Vtbl =
{
    IEnumFiltersImpl_QueryInterface,
    IEnumFiltersImpl_AddRef,
    IEnumFiltersImpl_Release,
    IEnumFiltersImpl_Next,
    IEnumFiltersImpl_Skip,
    IEnumFiltersImpl_Reset,
    IEnumFiltersImpl_Clone
};
