/*
 * Queue Manager (BITS) File Enumerator
 *
 * Copyright 2007, 2008 Google (Roy Shea, Dan Hipschman)
 *
 * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

#include "qmgr.h"
#include "wine/debug.h"

WINE_DEFAULT_DEBUG_CHANNEL(qmgr);

typedef struct
{
    IEnumBackgroundCopyFiles IEnumBackgroundCopyFiles_iface;
    LONG ref;
    IBackgroundCopyFile **files;
    ULONG numFiles;
    ULONG indexFiles;
} EnumBackgroundCopyFilesImpl;

static inline EnumBackgroundCopyFilesImpl *impl_from_IEnumBackgroundCopyFiles(IEnumBackgroundCopyFiles *iface)
{
    return CONTAINING_RECORD(iface, EnumBackgroundCopyFilesImpl, IEnumBackgroundCopyFiles_iface);
}

static HRESULT WINAPI EnumBackgroundCopyFiles_QueryInterface(IEnumBackgroundCopyFiles *iface,
        REFIID riid, void **ppv)
{
    EnumBackgroundCopyFilesImpl *This = impl_from_IEnumBackgroundCopyFiles(iface);

    TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppv);

    if (IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IEnumBackgroundCopyFiles))
    {
        *ppv = iface;
        IEnumBackgroundCopyFiles_AddRef(iface);
        return S_OK;
    }

    *ppv = NULL;
    return E_NOINTERFACE;
}

static ULONG WINAPI EnumBackgroundCopyFiles_AddRef(IEnumBackgroundCopyFiles *iface)
{
    EnumBackgroundCopyFilesImpl *This = impl_from_IEnumBackgroundCopyFiles(iface);
    ULONG ref = InterlockedIncrement(&This->ref);

    TRACE("(%p)->(%d)\n", This, ref);
    return ref;
}

static ULONG WINAPI EnumBackgroundCopyFiles_Release(IEnumBackgroundCopyFiles *iface)
{
    EnumBackgroundCopyFilesImpl *This = impl_from_IEnumBackgroundCopyFiles(iface);
    ULONG ref = InterlockedDecrement(&This->ref);
    ULONG i;

    TRACE("(%p)->(%d)\n", This, ref);

    if (ref == 0)
    {
        for(i = 0; i < This->numFiles; i++)
            IBackgroundCopyFile_Release(This->files[i]);
        HeapFree(GetProcessHeap(), 0, This->files);
        HeapFree(GetProcessHeap(), 0, This);
    }

    return ref;
}

/* Return reference to one or more files in the file enumerator */
static HRESULT WINAPI EnumBackgroundCopyFiles_Next(IEnumBackgroundCopyFiles *iface,
        ULONG celt, IBackgroundCopyFile **rgelt, ULONG *pceltFetched)
{
    EnumBackgroundCopyFilesImpl *This = impl_from_IEnumBackgroundCopyFiles(iface);
    ULONG fetched;
    ULONG i;
    IBackgroundCopyFile *file;

    TRACE("(%p)->(%d %p %p)\n", This, celt, rgelt, pceltFetched);

    /* Despite documented behavior, Windows (tested on XP) is not verifying
       that the caller set pceltFetched to zero.  No check here. */

    fetched = min(celt, This->numFiles - This->indexFiles);
    if (pceltFetched)
        *pceltFetched = fetched;
    else
    {
        /* We need to initialize this array if the caller doesn't request
           the length because length_is will default to celt.  */
        for (i = 0; i < celt; i++)
            rgelt[i] = NULL;

        /* pceltFetched can only be NULL if celt is 1 */
        if (celt != 1)
            return E_INVALIDARG;
    }

    /* Fill in the array of objects */
    for (i = 0; i < fetched; i++)
    {
        file = This->files[This->indexFiles++];
        IBackgroundCopyFile_AddRef(file);
        rgelt[i] = file;
    }

    return fetched == celt ? S_OK : S_FALSE;
}

/* Skip over one or more files in the file enumerator */
static HRESULT WINAPI EnumBackgroundCopyFiles_Skip(IEnumBackgroundCopyFiles *iface,
        ULONG celt)
{
    EnumBackgroundCopyFilesImpl *This = impl_from_IEnumBackgroundCopyFiles(iface);

    TRACE("(%p)->(%d)\n", This, celt);

    if (celt > This->numFiles - This->indexFiles)
    {
        This->indexFiles = This->numFiles;
        return S_FALSE;
    }

    This->indexFiles += celt;
    return S_OK;
}

static HRESULT WINAPI EnumBackgroundCopyFiles_Reset(IEnumBackgroundCopyFiles *iface)
{
    EnumBackgroundCopyFilesImpl *This = impl_from_IEnumBackgroundCopyFiles(iface);

    TRACE("(%p)\n", This);

    This->indexFiles = 0;
    return S_OK;
}

static HRESULT WINAPI EnumBackgroundCopyFiles_Clone(IEnumBackgroundCopyFiles *iface,
        IEnumBackgroundCopyFiles **ppenum)
{
    EnumBackgroundCopyFilesImpl *This = impl_from_IEnumBackgroundCopyFiles(iface);
    FIXME("(%p)->(%p): stub\n", This, ppenum);
    return E_NOTIMPL;
}

static HRESULT WINAPI EnumBackgroundCopyFiles_GetCount(IEnumBackgroundCopyFiles *iface,
        ULONG *puCount)
{
    EnumBackgroundCopyFilesImpl *This = impl_from_IEnumBackgroundCopyFiles(iface);
    TRACE("(%p)->(%p)\n", This, puCount);
    *puCount = This->numFiles;
    return S_OK;
}

static const IEnumBackgroundCopyFilesVtbl EnumBackgroundCopyFilesVtbl =
{
    EnumBackgroundCopyFiles_QueryInterface,
    EnumBackgroundCopyFiles_AddRef,
    EnumBackgroundCopyFiles_Release,
    EnumBackgroundCopyFiles_Next,
    EnumBackgroundCopyFiles_Skip,
    EnumBackgroundCopyFiles_Reset,
    EnumBackgroundCopyFiles_Clone,
    EnumBackgroundCopyFiles_GetCount
};

HRESULT EnumBackgroundCopyFilesConstructor(BackgroundCopyJobImpl *job, IEnumBackgroundCopyFiles **enum_files)
{
    EnumBackgroundCopyFilesImpl *This;
    BackgroundCopyFileImpl *file;
    ULONG i;

    TRACE("%p, %p)\n", job, enum_files);

    This = HeapAlloc(GetProcessHeap(), 0, sizeof *This);
    if (!This)
        return E_OUTOFMEMORY;

    This->IEnumBackgroundCopyFiles_iface.lpVtbl = &EnumBackgroundCopyFilesVtbl;
    This->ref = 1;

    /* Create array of files */
    This->indexFiles = 0;
    EnterCriticalSection(&job->cs);
    This->numFiles = list_count(&job->files);
    This->files = NULL;
    if (This->numFiles > 0)
    {
        This->files = HeapAlloc(GetProcessHeap(), 0,
                                This->numFiles * sizeof This->files[0]);
        if (!This->files)
        {
            LeaveCriticalSection(&job->cs);
            HeapFree(GetProcessHeap(), 0, This);
            return E_OUTOFMEMORY;
        }
    }

    i = 0;
    LIST_FOR_EACH_ENTRY(file, &job->files, BackgroundCopyFileImpl, entryFromJob)
    {
        IBackgroundCopyFile_AddRef(&file->IBackgroundCopyFile_iface);
        This->files[i] = &file->IBackgroundCopyFile_iface;
        ++i;
    }
    LeaveCriticalSection(&job->cs);

    *enum_files = &This->IEnumBackgroundCopyFiles_iface;
    return S_OK;
}
