#ifndef __FK2_OGG_VORBIS_H__
#define __FK2_OGG_VORBIS_H__

#include <vorbis/vorbisfile.h>
#include <string>
#include <vector>

#ifdef _MACOSX_
#include <OpenAL/al.h>
#include <OpenAL/alc.h>
#include <OpenAL/alut.h>
#else
#include <AL/al.h>
#include <AL/alc.h>
#include <AL/alut.h>
#endif

#include <FK/IDAdmin.h>
#include <FK/Vector.h>

#pragma comment(lib,"OpenAL32.lib")
#pragma comment(lib,"alut.lib")
#pragma comment(lib,"libogg.lib")
#pragma comment(lib,"libvorbis.lib")
#pragma comment(lib,"libvorbisfile.lib")

const unsigned int FK_OV_BUFSIZE = 4096;
const unsigned int FK_OV_DEFAULT_QUEUE_SIZE = 64;

class fk_Model;

class fk_AudioBase {
 protected:
	int				source_id;
	ALuint			source;
	unsigned int	queueSize;
	ALenum			format;
	long			rate;
	double			gain;
	bool			loopMode;
	double			loopStartTime, loopEndTime;

	static fk_Model	*listenerCamera;

	void			CreateID(void);
	void			EraseID(void);
	void			MakeOVInfo(OggVorbis_File *);

	static void		UpdateListener(void);

 public:
	fk_AudioBase(void);
	virtual ~fk_AudioBase();

	static bool		init(void);
	static bool		getInit(void);

	void			setGain(double);
	double			getGain(void);

	void			setQueueSize(int);
	int				getQueueSize(void);

	void			setLoopMode(bool);
	bool			getLoopMode(void);
	void			setLoopArea(double, double);
	double			getLoopStartTime(void);
	double			getLoopEndTime(void);

	static void		sleep(double);

	virtual bool	open(const std::string &) = 0;
	virtual bool	ready(void) = 0;
	virtual bool	play(void) = 0;
	virtual double	tell(void) = 0;
	virtual void	seek(double) = 0;
	void			pause(void);
	virtual void	stop(void) = 0;
	virtual void	end(void) = 0;

	static void			setListenerModel(fk_Model *);
	static void			setListenerModel(fk_Model &);
	static fk_Model *	getListenerModel(void);
};

class fk_AudioStream : public fk_AudioBase {
private:
	OggVorbis_File	vf;
	bool			ovOpenStatus, startStatus, endStatus;
	int				current;
	char			buffer[FK_OV_BUFSIZE];
	double			nowTime;

	void			StartQueue(bool);
	bool			PlayStream(void);
	void			UnQueue(bool);

public:

	fk_AudioStream(void);
	virtual ~fk_AudioStream();

	bool			open(const std::string &);
	bool			ready(void);
	bool			play(void);
	double			tell(void);
	void			seek(double);
	void			stop(void);
	void			end(void);
};

class fk_AudioOggBuffer : public fk_AudioBase {
 protected:
	bool				startStatus, endStatus;
	unsigned int		current, length;
	std::vector<char>	buffer;
	std::vector<int>	chunkSize;
	std::vector<double>	chunkTime;
	bool				surround;
	double				refDist;
	fk_Model			*ref_model;
	fk_Vector			sourcePos;


	void			ReadBuffer(OggVorbis_File *);
	void			StartQueue(bool);
	bool			PlayBuffer(void);
	void			UnQueue(bool);

public:

	fk_AudioOggBuffer(void);
	virtual ~fk_AudioOggBuffer();

	bool			open(const std::string &);
	bool			ready(void);
	bool			play(void);
	double			tell(void);
	void			seek(double);
	void			stop(void);
	void			end(void);

	void			setPosition(const fk_Vector &);
	void			setModel(fk_Model *);
	void			setModel(fk_Model &);
	void			setReferenceDist(double);
	void			disableSurround(void);

	fk_Model *		getModel(void);
	fk_Vector		getPosition(void);
	double			getReferenceDist(void);
	bool			getSurroundMode(void);
};

class fk_AudioWavBuffer : public fk_AudioOggBuffer {
 private:

	int				ReadHeaderWav(FILE *, int *, int *, int *, int *);
	bool			ReadBuffer(FILE *, int, int, int, int);

public:

	fk_AudioWavBuffer(void);
	virtual ~fk_AudioWavBuffer();

	bool			open(const std::string &);
};


#endif
