/*
 * List of components. (for internal use)
 *
 * Copyright (C) Hidenori TAKESHIMA <hidenori@a2.ctktv.ne.jp>
 *
 * 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 "config.h"

#include "windef.h"
#include "winbase.h"
#include "winerror.h"
#include "wine/obj_base.h"

#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(quartz);

#include "quartz_private.h"
#include "complist.h"



struct QUARTZ_CompList
{
	QUARTZ_CompListItem*	pFirst;
	QUARTZ_CompListItem*	pLast;
	CRITICAL_SECTION		csList;
};

struct QUARTZ_CompListItem
{
	IUnknown*	punk;
	QUARTZ_CompListItem*	pNext;
	QUARTZ_CompListItem*	pPrev;
	void*	pvData;
	DWORD	dwDataLen;
};


QUARTZ_CompList* QUARTZ_CompList_Alloc( void )
{
	QUARTZ_CompList*	pList;

	pList = (QUARTZ_CompList*)QUARTZ_AllocMem( sizeof(QUARTZ_CompList) );
	if ( pList != NULL )
	{
		/* construct. */
		pList->pFirst = NULL;
		pList->pLast = NULL;

		InitializeCriticalSection( &pList->csList );
	}

	return pList;
}

void QUARTZ_CompList_Free( QUARTZ_CompList* pList )
{
	QUARTZ_CompListItem*	pCur;
	QUARTZ_CompListItem*	pNext;

	if ( pList != NULL )
	{
		pCur = pList->pFirst;
		while ( pCur != NULL )
		{
			pNext = pCur->pNext;
			if ( pCur->punk != NULL )
				IUnknown_Release( pCur->punk );
			if ( pCur->pvData != NULL )
				QUARTZ_FreeMem( pCur->pvData );
			QUARTZ_FreeMem( pCur );
			pCur = pNext;
		}

		DeleteCriticalSection( &pList->csList );

		QUARTZ_FreeMem( pList );
	}
}

void QUARTZ_CompList_Lock( QUARTZ_CompList* pList )
{
	EnterCriticalSection( &pList->csList );
}

void QUARTZ_CompList_Unlock( QUARTZ_CompList* pList )
{
	LeaveCriticalSection( &pList->csList );
}

QUARTZ_CompList* QUARTZ_CompList_Dup(
	const QUARTZ_CompList* pList, BOOL fDupData )
{
	QUARTZ_CompList*	pNewList;
	const QUARTZ_CompListItem*	pCur;
	HRESULT	hr;

	pNewList = QUARTZ_CompList_Alloc();
	if ( pNewList == NULL )
		return NULL;

	pCur = pList->pFirst;
	while ( pCur != NULL )
	{
		if ( pCur->punk != NULL )
		{
			if ( fDupData )
				hr = QUARTZ_CompList_AddComp(
					pNewList, pCur->punk,
					pCur->pvData, pCur->dwDataLen );
			else
				hr = QUARTZ_CompList_AddComp(
					pNewList, pCur->punk, NULL, 0 );
			if ( FAILED(hr) )
			{
				QUARTZ_CompList_Free( pNewList );
				return NULL;
			}
		}
		pCur = pCur->pNext;
	}

	return pNewList;
}

static QUARTZ_CompListItem* QUARTZ_CompList_AllocComp(
	QUARTZ_CompList* pList, IUnknown* punk,
	const void* pvData, DWORD dwDataLen )
{
	QUARTZ_CompListItem*	pItem;

	pItem = (QUARTZ_CompListItem*)QUARTZ_AllocMem( sizeof(QUARTZ_CompListItem) );
	if ( pItem == NULL )
		return NULL;

	pItem->pvData = NULL;
	pItem->dwDataLen = 0;
	if ( pvData != NULL )
	{
		pItem->pvData = (void*)QUARTZ_AllocMem( dwDataLen );
		if ( pItem->pvData == NULL )
		{
			QUARTZ_FreeMem( pItem );
			return NULL;
		}
		memcpy( pItem->pvData, pvData, dwDataLen );
		pItem->dwDataLen = dwDataLen;
	}

	pItem->punk = punk; IUnknown_AddRef(punk);

	return pItem;
}

HRESULT QUARTZ_CompList_AddComp(
	QUARTZ_CompList* pList, IUnknown* punk,
	const void* pvData, DWORD dwDataLen )
{
	QUARTZ_CompListItem*	pItem;

	pItem = QUARTZ_CompList_AllocComp( pList, punk, pvData, dwDataLen );
	if ( pItem == NULL )
		return E_OUTOFMEMORY;

	if ( pList->pFirst != NULL )
		pList->pFirst->pPrev = pItem;
	else
		pList->pLast = pItem;
	pItem->pNext = pList->pFirst;
	pList->pFirst = pItem;
	pItem->pPrev = NULL;

	return S_OK;
}

HRESULT QUARTZ_CompList_AddTailComp(
	QUARTZ_CompList* pList, IUnknown* punk,
	const void* pvData, DWORD dwDataLen )
{
	QUARTZ_CompListItem*	pItem;

	pItem = QUARTZ_CompList_AllocComp( pList, punk, pvData, dwDataLen );
	if ( pItem == NULL )
		return E_OUTOFMEMORY;

	if ( pList->pLast != NULL )
		pList->pLast->pNext = pItem;
	else
		pList->pFirst = pItem;
	pItem->pPrev = pList->pLast;
	pList->pLast = pItem;
	pItem->pNext = NULL;

	return S_OK;
}

HRESULT QUARTZ_CompList_RemoveComp( QUARTZ_CompList* pList, IUnknown* punk )
{
	QUARTZ_CompListItem*	pCur;

	pCur = QUARTZ_CompList_SearchComp( pList, punk );
	if ( pCur == NULL )
		return S_FALSE; /* already removed. */

	/* remove from list. */
	if ( pCur->pNext != NULL )
		pCur->pNext->pPrev = pCur->pPrev;
	else
		pList->pLast = pCur->pPrev;
	if ( pCur->pPrev != NULL )
		pCur->pPrev->pNext = pCur->pNext;
	else
		pList->pFirst = pCur->pNext;

	/* release this item. */
	if ( pCur->punk != NULL )
		IUnknown_Release( pCur->punk );
	if ( pCur->pvData != NULL )
		QUARTZ_FreeMem( pCur->pvData );
	QUARTZ_FreeMem( pCur );

	return S_OK;
}

QUARTZ_CompListItem* QUARTZ_CompList_SearchComp(
	QUARTZ_CompList* pList, IUnknown* punk )
{
	QUARTZ_CompListItem*	pCur;

	pCur = pList->pFirst;
	while ( pCur != NULL )
	{
		if ( pCur->punk == punk )
			return pCur;
		pCur = pCur->pNext;
	}

	return NULL;
}

QUARTZ_CompListItem* QUARTZ_CompList_SearchData(
	QUARTZ_CompList* pList, const void* pvData, DWORD dwDataLen )
{
	QUARTZ_CompListItem*	pCur;

	pCur = pList->pFirst;
	while ( pCur != NULL )
	{
		if ( pCur->dwDataLen == dwDataLen &&
		     !memcmp( pCur->pvData, pvData, dwDataLen ) )
			return pCur;
		pCur = pCur->pNext;
	}

	return NULL;
}

QUARTZ_CompListItem* QUARTZ_CompList_GetFirst(
	QUARTZ_CompList* pList )
{
	return pList->pFirst;
}

QUARTZ_CompListItem* QUARTZ_CompList_GetLast(
	QUARTZ_CompList* pList )
{
	return pList->pLast;
}

QUARTZ_CompListItem* QUARTZ_CompList_GetNext(
	QUARTZ_CompList* pList, QUARTZ_CompListItem* pPrev )
{
	return pPrev->pNext;
}

QUARTZ_CompListItem* QUARTZ_CompList_GetPrev(
	QUARTZ_CompList* pList, QUARTZ_CompListItem* pNext )
{
	return pNext->pPrev;
}

IUnknown* QUARTZ_CompList_GetItemPtr( QUARTZ_CompListItem* pItem )
{
	return pItem->punk;
}

const void* QUARTZ_CompList_GetDataPtr( QUARTZ_CompListItem* pItem )
{
	return pItem->pvData;
}

DWORD QUARTZ_CompList_GetDataLength( QUARTZ_CompListItem* pItem )
{
	return pItem->dwDataLen;
}
