#include "MemUtils.h"
#include "CFilePro.h"

#include "GSOS_Icons.h"

#define	ICONS_TURNED_ON		0

GSOS_IconArrayH		g_iconsA[256] = { 0 };

static	void		GSOS_GetIndIconData(
	GSOS_IconRecP		iconRecP, 
	ushort				indexS, 
	GSOS_IconDataRec	**dataRecPP)
{
	*dataRecPP = &iconRecP->icon_dataA[0];
	
	while (indexS--) {
		ushort		lenS = GetRboShort((*dataRecPP)->data_length);
		
		if (lenS) {
			*dataRecPP = (GSOS_IconDataRec *)((char *)dataRecPP) + lenS;
		} else {
			*dataRecPP	= NULL;
			indexS		= 0;
		}
	}
}

static	void		GSOS_GetIconData(
	GSOS_IconDataRec	*dataRecP, 
	GSOS_IconSizeType	size, 
	GSOS_IconType		type, 
	ushort				*sizeS, 
	char				**dataPP)
{
	GSOS_Icon	*iconP;
	
	if (size == GSOS_IconSize_LARGE) {
		iconP = &dataRecP->big_icon;
	} else {
		char	*dataA = (char *)&dataRecP->big_icon;
		
		iconP = (GSOS_Icon *)dataA[GetRboShort(dataRecP->big_icon.num_bytes) * 2];
	}

	*sizeS = GetRboShort(iconP->num_bytes);
	
	if (type == GSOS_Icon_IMAGE) {
		*dataPP	= &iconP->icon[0];
	} else {
		*dataPP	= &iconP->icon[*sizeS];
	}
}

static	OSErr		GSOS_IconGroupToSuite(
	IconDataGroup	*groupP, 
	Handle			suiteH)
{
	OSErr		err = noErr;
	
	return err;	
}

static	OSErr		GSOS_AddCustomIcon(
	ushort			fileType, 
	ushort			auxType, 
	char			*nameZ, 
	IconDataGroup	*groupP)
{
	OSErr				err = noErr;
	Handle				suiteH;
	GSOS_IconArrayH		*recHP = NULL;
	
	if (!err) err = NewIconSuite(&suiteH);
	if (!err) err = GSOS_IconGroupToSuite(groupP, suiteH);

	if (!err) {	
		GSOS_GetCustomIcon(fileType, auxType, nameZ, &recHP);
		
		ASSERT(*recHP == NULL);
		if (*recHP == NULL) {
			*recHP = (GSOS_IconArrayH)TrackNewHandleClear("GSOS icon array", sizeof(GSOS_IconArrayRec));
			if (*recHP == NULL) err = IC_Err_OUT_OF_MEMORY;
			
			if (!err) {
				(***recHP).iconH	= suiteH;
				(***recHP).auxType	= auxType;
				strcpy((***recHP).nameAC, nameZ);
			}
		}
	}
	
	if (err) {
		if (suiteH) {
			DisposeIconSuite(suiteH, TRUE);
		}
	}
	
	return err;
}

void		GSOS_AddIconFile(CFilePro *fileP)
{
	#if ICONS_TURNED_ON
	Handle	iconFileH = fileP->CopyFileToHandle(FALSE);
	
	if (iconFileH) {
		IconDataGroup		iconGroup;
		GSOS_IconDataRec	*dataRecP;
		GSOS_IconSizeType	sizeS; 
		GSOS_IconType		typeS;
		short				indexS = 0;
		char				bufAC[256];
		OSErr				err = noErr;
		
		HLock(iconFileH);
		
		do {
			GSOS_GetIndIconData((GSOS_IconRecP)*iconFileH, indexS, &dataRecP);
			
			if (dataRecP) {

				FOR_EACH_ICON_SIZE(sizeS) {
					FOR_EACH_ICON_TYPE(typeS) {
						GSOS_GetIconData(
							dataRecP, sizeS, typeS, 
							&iconGroup[sizeS][typeS].sizeS, 
							&iconGroup[sizeS][typeS].dataP);
					}
				}

				err = GSOS_AddCustomIcon(
					fileP->GetFileType(), 
					fileP->GetAuxType(), 
					fileP->GetName(bufAC), 
					&iconGroup);

				indexS++;
			}
			
		} while (!err && dataRecP);

		HUnlock(iconFileH);
		TrackDisposeHandle(iconFileH);
	}
	#endif
}
/*
*/

static	void		GSOS_PostDisposeR(GSOS_IconArrayH curRecH)
{
	if (curRecH) {
		GSOS_PostDisposeR((**curRecH).next);
		
		ASSERT((**curRecH).iconH);
		if ((**curRecH).iconH) {
			DisposeIconSuite((**curRecH).iconH, TRUE);
		}
		
		TrackDisposeHandle((Handle)curRecH);
	}
}

void		GSOS_PostDispose(void)
{
	ushort	fileType;
	
	for (fileType = 0; fileType < 256; fileType++) {
		GSOS_PostDisposeR(g_iconsA[fileType]);
		g_iconsA[fileType] = NULL;
	}
}

Boolean		GSOS_HasCustomIcon(ushort fileType, ushort auxType, char *nameZ)
{
	#if ICONS_TURNED_ON
		return GSOS_GetCustomIcon(fileType, auxType, nameZ) != NULL;
	#else
		return FALSE;
	#endif
}

static	Boolean		GSOS_FoundIcon(
	GSOS_IconArrayH	recH, 
	ushort			fileType, 
	ushort			auxType, 
	char			*nameZ)
{
	return 
			(recH != NULL)
		&& (*recH != NULL)
		&& (**recH).iconH != NULL 
		&& (**recH).auxType == auxType;
}
	

Handle		GSOS_GetCustomIcon(
	ushort				fileType, 
	ushort				auxType, 
	char				*nameZ, 
	GSOS_IconArrayH		**recHPP0)
{
	Boolean				doneB	= FALSE;
	Handle				iconH	= NULL;
	GSOS_IconArrayH		*recHP;
	
	recHP = &g_iconsA[fileType];
	
	do {
		if (GSOS_FoundIcon(*recHP, fileType, auxType, nameZ)) {
			iconH = (***recHP).iconH;
			
			if (recHPP0)	{
				*recHPP0 = recHP;
			}
					
			doneB = TRUE;
		} else {
			doneB = *recHP == NULL;

			if (!doneB) {
				recHP = &(***recHP).next;
			}
		}
	} while (!doneB);
	
	if (GSOS_FoundIcon(*recHP, fileType, auxType, nameZ)) {
		iconH = (***recHP).iconH;
	} else if (*recHP && (***recHP).next != NULL) {
		for (
			;
			recHP != NULL;
			recHP = &(***recHP).next
		) {
			if ((***recHP).auxType == auxType) {
				iconH = (***recHP).iconH;
				recHP = NULL;
			}
		}
	}
	
	return iconH;
}