//////////////////////////////////////////////////////////////////////////////
//
// Asura_Sound_Event_Storage.cpp
//
// Copyright (c) 2006 Rebellion. All rights reserved.
//
// Description:
//
//     storage and lookups of sound events and related objects
//
//////////////////////////////////////////////////////////////////////////////

// I N C L U D E S ///////////////////////////////////////////////////////////

#include "Core/Asura.h"

// This file's header.
#include "Sound/Asura_Sound_Event_Storage.h"

// Asura includes
#include "Core/Asura_HashTree.h"
#include "Core/Asura_Stream.h"
#include "Core/Resources/Asura_ResourceSet.h"
#include "Debugging/Asura_Assert.h"
#include "Sound/Asura_Sound_Event.h"

// Tools includes
#ifdef ASURA_TOOLS
#include "Sound/Tools_SoundEvent_System.h"
#endif //#ifdef ASURA_TOOLS

// C L A S S   I M P L E M E N T A T I O N S /////////////////////////////////

/*---------------------------**
** Asura_Sound_Event_Storage **
**---------------------------*/

Asura_ResourceSet<Asura_Sound_Sample> Asura_Sound_Event_Storage::s_xSampleContainer("Sound Samples");
Asura_ResourceSet<Asura_Sound_Event_Mapping> Asura_Sound_Event_Storage::s_xEventMappingContainer("Sound Events");



void Asura_Sound_Event_Storage::Shutdown()
{
	s_xEventMappingContainer.Reset();
	s_xSampleContainer.Reset();
}

void Asura_Sound_Event_Storage::Reset()
{
}


const Asura_Sound_Event* Asura_Sound_Event_Storage::FindEvent(Asura_Hash_ID uHashID)
{
	Asura_Sound_Event_Mapping* pxResult = s_xEventMappingContainer.GetResource(uHashID);
	if (pxResult)
	{
		return pxResult->m_pxEvent;
	}
	return NULL;
}




const Asura_Sound_Sample* Asura_Sound_Event_Storage::FindSample(Asura_Hash_ID uHashID)
{
	return s_xSampleContainer.GetResource(uHashID);
}


#ifdef ASURA_TOOLS
u_int Asura_Sound_Event_Storage::GetNumberOfEvents()
{
	return s_xEventMappingContainer.GetNumResources();
}

Asura_Sound_Event* Asura_Sound_Event_Storage::GetEventByHash(u_int uHashID)
{
	Asura_Sound_Event_Mapping* pxResult = s_xEventMappingContainer.GetResource(uHashID);
	if (pxResult)
	{
		return pxResult->m_pxEvent;
	}
	return NULL;
}

Asura_Sound_Event* Asura_Sound_Event_Storage::GetEventByIndex(u_int uIndex)
{
	Asura_Sound_Event_Mapping* pxResult = s_xEventMappingContainer.GetResourceByIndex(uIndex);
	if (pxResult)
	{
		return pxResult->m_pxEvent;
	}
	return NULL;
}

u_int Asura_Sound_Event_Storage::GetNumberOfSamples()
{
	return s_xSampleContainer.GetNumResources();
}

Asura_Sound_Sample* Asura_Sound_Event_Storage::GetSampleByHash(u_int uHashID)
{
	return s_xSampleContainer.GetResource(uHashID);
}

Asura_Sound_Sample* Asura_Sound_Event_Storage::GetSampleByIndex(u_int uIndex)
{
	return s_xSampleContainer.GetResourceByIndex(uIndex);
}

bool Asura_Sound_Event_Storage::RenameSample(const char* szOldName,const char* szNewName)
{
	Asura_Hash_ID uOldHash = Asura_GetHashID(szOldName);
	Asura_Hash_ID uNewHash = Asura_GetHashID(szNewName);

	//make sure the sample exists
	Asura_Sound_Sample* pxSample = GetSampleByHash(uOldHash);
	if(!pxSample) return false;

	//see if the hash replacement is okay
	if(uOldHash != uNewHash)
	{
		if(!s_xSampleContainer.RelocateResource(uOldHash,uNewHash)) return false;
	}

	pxSample->m_xSampleName = szNewName;
	pxSample->m_uHashID = uNewHash;

	return true;
}

bool Asura_Sound_Event_Storage::RenameEvent(const char* szOldName,const char* szNewName)
{
	Asura_Hash_ID uOldHash = Asura_GetHashID(szOldName);
	Asura_Hash_ID uNewHash = Asura_GetHashID(szNewName);

	//make sure the event exists
	Asura_Sound_Event* pxEvent = GetEventByHash(uOldHash);
	if(!pxEvent) return false;

	//see if the hash replacement is okay
	if(uOldHash != uNewHash)
	{
		if(!s_xEventMappingContainer.RelocateResource(uOldHash,uNewHash)) return false;
	}

	pxEvent->m_xEventName = szNewName;
	pxEvent->m_uHashID = uNewHash;

	return true;
}

void Asura_Sound_Event_Storage::DeleteEvent(Asura_Sound_Event* pxEvent)
{
	if(!pxEvent) return;
	

	//delete the event mapping from the resource sset 
	#ifdef ASURA_ASSERT
		bool bOK = 
	#endif
	s_xEventMappingContainer.DeleteResource( pxEvent->GetHashID() );
	Asura_Assert(bOK, "failed to delete event from resource set");

}

void Asura_Sound_Event_Storage::DeleteSample(Asura_Sound_Sample* pxSample)
{
	if(!pxSample) return;
	

	//delete the sample from the resource set
	#ifdef ASURA_ASSERT
		bool bOK = 
	#endif
	s_xSampleContainer.DeleteResource(pxSample->GetHashID());
	Asura_Assert(bOK, "failed to delete sample from resource set");

}


#endif // ASURA_TOOLS

Asura_Sound_Sample* Asura_Sound_Event_Storage::CreateSample(const char* szName, bool& bAlreadyExists)
{
	Asura_Hash_ID uSampleHash = Asura_GetHashID(szName);

	//search for an existing sample
	Asura_Sound_Sample* pxSample = s_xSampleContainer.GetResource(uSampleHash);
	if(pxSample)
	{
		bAlreadyExists = true;
		//add a reference for the current resource bank
		s_xSampleContainer.AddResource(uSampleHash, *pxSample, false);
	}
	else
	{
		//create a new sample and add it
		bAlreadyExists = false;
		pxSample = new Asura_Sound_Sample(szName);
		s_xSampleContainer.AddResource(uSampleHash, *pxSample, true);
	}
	return pxSample;
}

Asura_Sound_Event* Asura_Sound_Event_Storage::CreateEvent(const char* szName, bool& bAlreadyExists)
{
	Asura_Hash_ID uEventHash = Asura_GetHashID(szName);

	//search for an existing mapping
	Asura_Sound_Event_Mapping* pxMapping = s_xEventMappingContainer.GetResource(uEventHash);
	if(pxMapping)
	{
		bAlreadyExists = true;
		//add a reference for the current resource bank
		s_xEventMappingContainer.AddResource(uEventHash, *pxMapping, false);
	}
	else
	{
		//create a new event and mapping and add them
		bAlreadyExists = false;
		pxMapping = new Asura_Sound_Event_Mapping;
		pxMapping->m_pxEvent = new Asura_Sound_Event(szName);
		pxMapping->m_pxEvent->m_uMappingCount++;

		s_xEventMappingContainer.AddResource(uEventHash, *pxMapping, true);
	}
	return pxMapping->m_pxEvent;
}
#ifndef ASURA_TOOLS
void Asura_Sound_Event_Storage::AddEventMapping(Asura_Hash_ID uNewHashID, Asura_Hash_ID uExistingHashID)
{
	//Make sure the target event exists
	Asura_Sound_Event* pxEvent = const_cast<Asura_Sound_Event*>(FindEvent(uExistingHashID));
	if(!pxEvent)
	{
		Asura_Assert(0,"Failed to find target event for sound event mapping");
		return;
	}	
	
	//search for an existing mapping
	Asura_Sound_Event_Mapping* pxMapping = s_xEventMappingContainer.GetResource(uNewHashID);
	if(pxMapping)
	{
		//add a reference for the current resource bank
		s_xEventMappingContainer.AddResource(uNewHashID, *pxMapping, false);
	}
	else
	{
		//create a new mapping and add to the resource set
		pxMapping = new Asura_Sound_Event_Mapping;
		pxMapping->m_pxEvent = pxEvent;
		pxMapping->m_pxEvent->m_uMappingCount++;

		s_xEventMappingContainer.AddResource(uNewHashID, *pxMapping, true);
	}
}
#endif //!defined ASURA_TOOLS



Asura_Sound_Event_Mapping::~Asura_Sound_Event_Mapping()
{
	m_pxEvent->m_uMappingCount--;
	if(!m_pxEvent->m_uMappingCount) delete m_pxEvent;
}

//eof
