#ifndef _SONG_H_
#define _SONG_H_

#include "ISound.h"

#define MAX_TRACKS 3
#define MAX_BARS 20
#define BAR_LENGTH 4.0f //4 is a good number as it creates 4:4 timing, to do other non 1:1 timing is more complicated
#define NUM_SCALES 7
#define SCALE_LENGTH 7
#define VOLUME_AMPLITUDE 10000

typedef unsigned int UInt;
typedef unsigned char Uint8;
typedef short int Sint16;

class SongSection
{
	public:
	SongSection();
	~SongSection();

	bool Initialise(const UInt &bpm, const UInt &length);
	Sint16* GetBuffer(const UInt &position, const int &len);
	void Output();

	UInt GetSectionLength() { return m_timePerSection; }

	enum eBarNoteLength
	{
		eOneNote = 0,
		eTwoNotes,
		eFourNotes,
		eEightNotes,
		eNumNotesTypes
	};

	struct SBar
	{
		SBar() : pFrequencies(0), numFreqs(0), timePerFreq(0) {}
		~SBar() { if(pFrequencies) delete[] pFrequencies; }

		float* pFrequencies;
		UInt numFreqs, timePerFreq;
	};

	struct STrack
	{
		STrack() : pBars(0), numBars(0), pUniqueBars(0), numUniqueBars(0) {}
		~STrack() { if(pBars) delete[] pBars; if(pUniqueBars) delete[] pUniqueBars; }
		SBar** pBars;
		SBar* pUniqueBars;
		UInt numBars, numUniqueBars, timePerBar;
	};

	protected:
	STrack* m_pTracks;
	static float* m_pTrackDegreesOnWave;
	UInt m_numTracks, m_timePerSection;
};

class Song : public ISound
{
	public:
	Song();
	~Song();

	void Initialise(const bool &bPreCreate, const UInt &bpm, const UInt &numUniqueSections, const UInt &lengthInSections, const UInt &timePerSection);
	void Output();
	virtual Sint16* GetBuffer(const UInt &position, const int &len, bool isLooping = false);

	protected:
	Sint16* GetDynamicBuffer(const UInt &pos, const int &len);
	char* m_name;

	bool m_bIsPreCreated;
	UInt m_lastBufferRequested;
	Sint16** m_pSongData;
	UInt m_numSampleSets;

	SongSection** m_pSongSections;
	SongSection* m_pUniqueSections;
	UInt m_numSections, m_length, m_timePerSection, m_bpm, m_lastPointPlayed;
};

#endif
