#include "CDTrack.h"

#include <ctype.h>
#include <stdlib.h>
#include <string.h>

#include "DigitalCD.h"

#include "WimpLib:Array.h"
#include "WimpLib:Exception.h"
#include "WimpLib:File.h"
#include "WimpLib:mem.h"
#include "WimpLib:Message.h"
#include "WimpLib:Task.h"
#include "WimpLib:Utils.h"
#include "WimpLib:Window.h"

#include "CDDesc.h"
#include "DocEvents.h"

struct CDTrack
{
	CDDesc*      pDesc;
	const char*  title;
	const char*  author;
	const char*  collective;
	int          nr;
};

CDTrack* throw_New_CDTrack(CDDesc* pDesc)
{
	CDTrack* This = throw_mem_alloc(sizeof(CDTrack));

	try
	{
		This->pDesc = pDesc;
		This->title = NULL;
		This->author = throw_StrCol_Add(DigitalCD.pArtistsCol, NULL);
		This->collective = throw_StrCol_Add(DigitalCD.pCollectivesCol, NULL);
		This->nr = 0;
	}
	catch
	{
		mem_free(This);
		throw_current();
	}
	catch_end

	return This;
}

void Delete_CDTrack(CDTrack* This)
{
	if (This)
	{
		mem_free(This->title);
		StrCol_Remove(DigitalCD.pArtistsCol, This->author);
		StrCol_Remove(DigitalCD.pCollectivesCol, This->collective);
		mem_free(This);
	}
}

void throw_CDTrack_Copy(CDTrack* This, const CDTrack* pTrack)
{
	throw_mem_setstring(&This->title, pTrack->title);
	throw_StrCol_Set(DigitalCD.pArtistsCol, &This->author, pTrack->author);
	throw_StrCol_Set(DigitalCD.pCollectivesCol, &This->collective, pTrack->collective);
}

void throw_CDTrack_Clear(CDTrack* This)
{
	throw_mem_setstring(&This->title, NULL);
	throw_StrCol_Set(DigitalCD.pArtistsCol, &This->author, NULL);
	throw_StrCol_Set(DigitalCD.pCollectivesCol, &This->collective, NULL);
}

CDDesc* CDTrack_GetCDDesc(const CDTrack* This)
{
	return This->pDesc;
}

const char* CDTrack_GetLabel(const CDTrack* This)
{
	const char* text = This->title;

	if ((text == NULL) || !*text)
		text = SPrintf(Msg_Lookup("UnkTrack: Track %d"), This->nr);

	return text;
}

const char* CDTrack_GetMetaString(const CDTrack* This, EMetaId id)
{
	switch(id)
	{
		case EMetaId_StreamTitle: return This->title ? This->title : &nil; break;
		case EMetaId_StreamArtist: return This->author ? This->author : &nil; break;
		case EMetaId_StreamCollective: 	return This->collective ? This->collective : &nil; break;
	}

	return &nil;
}

int CDTrack_GetOrder(const CDTrack* This)
{
	return This->nr;
}

bool throw_CDTrack_SetMetaString(CDTrack* This, EMetaId id, const char* pString)
{
	StrCol* pCol = NULL;
	const char** ppText = NULL;

	switch(id)
	{
		case EMetaId_StreamCollective:
		{
			pCol = DigitalCD.pCollectivesCol;
			ppText = &This->collective;
		}
		break;
		case EMetaId_StreamArtist:
		{
			pCol = DigitalCD.pArtistsCol;
			ppText = &This->author;
		}
		break;
		case EMetaId_StreamTitle:
		{
			ppText = &This->title;
		}
		break;
	}

	if (ppText == NULL) return false;

	if (pCol != NULL)
	{
		if (!strcmp(nvl(*ppText), nvl(pString)))
			return false;

		return throw_StrCol_Set(pCol, ppText, pString);
	}

	return throw_mem_setstring(ppText, pString);
}

void CDTrack_SetOrder(CDTrack* This, int nr)
{
	This->nr = nr;
}

void CDTrack_RefreshViews(const CDTrack* This, void* pSender, bool bModified)
{
	try
	{
		DocEvent e = {EDocEvent_UpdateElement, This, NULL};
		DocEvents_NotifyListeners(pSender, &e);
	}
	catch
	{
		App_ReportException();
	}
	catch_end

	if (bModified) CDDesc_SetModifiedFlag(This->pDesc, true);
}
