/*
 * List of components. (for internal use)
 *
 * hidenori@a2.ctktv.ne.jp
 */

#include "config.h"

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

#include "debugtools.h"
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;
}
