#pragma once

#include "..\munga\audrend.h"
#include "l4audhdw.h"
#include "l4audio.h"
#include "l4audres.h"
#include "openal/al.h"


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ L4AudioRenderer ~~~~~~~~~~~~~~~~~~~~~~~~~~~~

class L4AudioRenderer:
	public AudioRenderer
{
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Construction, Destruction, Testing
//
public:
	L4AudioRenderer(
		RendererRate render_rate,
		Logical mission_review_mode
	);
	~L4AudioRenderer();

	Logical
		TestInstance() const;

	virtual void ReleaseSourceSet(SourceSet &sourceSet);

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Renderer support
//
public:
	void
		Initialize();
public:

	void
		NotifyOfNewInterestingEntity(Entity *interesting_entity);
	void
		NotifyOfBecomingUninterestingEntity(Entity *uninteresting_entity);

protected:
	void
		ExecuteImplementation(
			RendererComplexity complexity_update,
			RendererOrigin::InterestingEntityIterator *iterator
		);

private:
	void
		LoadMissionImplementation(Mission *mission);
	void
		ShutdownImplementation();
	void
		SuspendImplementation();
	void
		ResumeImplementation();

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Audio hardware accessors
//
public:
/*	AudioCard*
		GetFrontCard();
	AudioCard*
		GetRearCard();*/

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Audio Source support
//
public:
	void
		StartRequest(L4AudioSource *audio_source);
	void
		StopRequest(L4AudioSource *audio_source);

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Private methods
//
private:
	void
		CalculateMix();
	void
		RunningSourceCheckup();
	//void
	//	RunningAudioSourceSort();
	void
		DormantSourceCheckup();
	void
		AudioSourceStopMaintenance(L4AudioSource *source);
	void
		AudioSourceSuspendMaintenance(L4AudioSource *source);
		
	Logical
     RequestAudioResources(
			L4AudioSource *audio_source,
			SourceSet *source_result
		);
	Logical
		RequestAudioChannels(
			AudioVoiceCount voices_requested,
			SourceSet *source_request
		);

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Private data
//
private:
	Logical
  	missionReviewMode;

/*	AudioHardware
		audioHardware;*/
	L4AudioResourceManager
  	audioResourceManager;
		
	AudioFrameCount
		nextCalculateMixFrame;

	typedef VChainOf<L4AudioSource*, AudioWeighting>
		RunningSourceSocket;
	typedef VChainIteratorOf<L4AudioSource*, AudioWeighting>
		RunningSourceIterator;

	RunningSourceSocket
		runningAudioSourceSocket;

	typedef ChainOf<L4AudioSource*>
		DormantSourceSocket;
	typedef ChainIteratorOf<L4AudioSource*>
		DormantSourceIterator;

	DormantSourceSocket
		dormantAudioSourceSocket;
		
	typedef VChainOf<L4AudioSource*, Enumeration>
		MixingSourceSocket;			
	typedef VChainIteratorOf<L4AudioSource*, Enumeration>
		MixingSourceIterator;
		
	MixingSourceSocket
		mixingAudioSourceSocket;
};

//~~~~~~~~~~~~~~~~~~~~~~~~~ L4AudioRenderer inlines ~~~~~~~~~~~~~~~~~~~~~~~~

/*inline AudioCard*
  L4AudioRenderer::GetFrontCard()
{
  Check(this);
  return audioHardware.GetFrontCard();
}

inline AudioCard*
  L4AudioRenderer::GetRearCard()
{
  Check(this);
  return audioHardware.GetRearCard();
}*/

//~~~~~~~~~~~~~~~~~~~~~~ L4AudioRenderer profile macros ~~~~~~~~~~~~~~~~~~~~

#if defined(TRACE_AUDIO_RENDERER_RUNNING_SOURCES)
	extern BitTrace Audio_Renderer_Running_Sources;
	#define SET_AUDIO_RUNNING_SOURCES() Audio_Renderer_Running_Sources.Set()
	#define CLEAR_AUDIO_RUNNING_SOURCES() Audio_Renderer_Running_Sources.Clear()
#else
	#define SET_AUDIO_RUNNING_SOURCES()
	#define CLEAR_AUDIO_RUNNING_SOURCES()
#endif

#if defined(TRACE_AUDIO_RENDERER_RUNNING_SORT)
	extern BitTrace Audio_Renderer_Running_Sort;
	#define SET_AUDIO_RUNNING_SORT() Audio_Renderer_Running_Sort.Set()
	#define CLEAR_AUDIO_RUNNING_SORT() Audio_Renderer_Running_Sort.Clear()
#else
	#define SET_AUDIO_RUNNING_SORT()
	#define CLEAR_AUDIO_RUNNING_SORT()
#endif

#if defined(TRACE_AUDIO_RENDERER_CALCULATE_MIX)
	extern BitTrace Audio_Renderer_Calculate_Mix;
	#define SET_AUDIO_CALCULATE_MIX() Audio_Renderer_Calculate_Mix.Set()
	#define CLEAR_AUDIO_CALCULATE_MIX() Audio_Renderer_Calculate_Mix.Clear()
#else
	#define SET_AUDIO_CALCULATE_MIX()
	#define CLEAR_AUDIO_CALCULATE_MIX()
#endif

#if defined(TRACE_AUDIO_RENDERER_EXECUTE_SOURCES)
	extern BitTrace Audio_Renderer_Execute_Sources;
	#define SET_AUDIO_EXECUTE_SOURCES() Audio_Renderer_Execute_Sources.Set()
	#define CLEAR_AUDIO_EXECUTE_SOURCES() Audio_Renderer_Execute_Sources.Clear()
#else
	#define SET_AUDIO_EXECUTE_SOURCES()
	#define CLEAR_AUDIO_EXECUTE_SOURCES()
#endif

#if defined(TRACE_AUDIO_RENDERER_DORMANT_SOURCES)
	extern BitTrace Audio_Renderer_Dormant_Sources;
	#define SET_AUDIO_DORMANT_SOURCES() Audio_Renderer_Dormant_Sources.Set()
	#define CLEAR_AUDIO_DORMANT_SOURCES() Audio_Renderer_Dormant_Sources.Clear()
#else
	#define SET_AUDIO_DORMANT_SOURCES()
	#define CLEAR_AUDIO_DORMANT_SOURCES()
#endif
