#ifndef _SOUNDMANAGER_H_
#define _SOUNDMANAGER_H_ //buy mum pc microphone

#include "TSingleton.h"
#include "IEventListener.h"
#include "SDL.h"

#include <vector>

typedef short int Sint16;
typedef unsigned short int Uint16;
typedef unsigned char Uint8;
typedef unsigned int SoundID;
typedef unsigned int SoundInstanceID;
typedef unsigned int UInt;

class ISound;

class SoundManager : public TSingleton<SoundManager>, public IEventListener
{
	public:
	SoundManager();
	~SoundManager();

	void Initialise(int freq = 44100, Uint16 samples = 1024, Uint8 channels = 1);
	void Shutdown();

	SoundID CreateSoundSong(const bool &bPreCreate, const UInt &bpm, const UInt &numUniqueSections, const UInt &lengthInSections, const UInt &timePerSection);

	SoundInstanceID PlaySoundID(const SoundID &sid, bool loop = false); //Implement error handling by exceptions!!
	bool PauseSound(const SoundInstanceID &siid);
	bool StopSound(const SoundInstanceID &siid);

	void Update(); //Should be called in the same style as the render loop, as quickly as possible.

	void Output();
	void IncreaseVolume();
	void DecreaseVolume();

	void HandleAudioBuffer(void* userdata, Uint8* stream, int len);
	SDL_AudioSpec* GetAudioSpec() { return m_pAudioSpec; }

	virtual bool HandleEvent(IEvent* pEvent);

	//Mixes pBuf2 into pBuf1, sz refers to pBuf2's size
	static void MixBuffers(Sint16* pBuf1, Sint16* pBuf2, size_t sz);

	//SDL function that basically just calls the non static version.
	static void SDLAudioCallback(void *userdata, Uint8 *stream, int len);

	protected:
	void ApplyVolumeToStream(Sint16* pStream, size_t sz);
	struct SoundInstance
	{
		SoundInstance() : pSound(0), isPaused(true), isLooping(false) {}
		ISound* pSound;
		bool isPaused;
		bool isLooping;
		unsigned long position;
	};

	std::vector<ISound*> m_vSounds;
	std::vector<SoundInstance*> m_vInstances;

	unsigned long m_lastUpdate;
	SDL_AudioSpec* m_pAudioSpec;
	int m_volume;
};

//15450
//9270
//
//
//

#endif
