/*--------------------------------------------------------------------
Includos*/

	#include "CSoundSceneNode.h"

/*--------------------------------------------------------------------
Declaracion global de funciones*/

	//Constructor
	CSoundSceneNode::CSoundSceneNode(ISceneNode* parent,ISceneManager* mgr,s32 id):ISceneNode(parent,mgr,id)
	{
		mesh = mgr->addEmptySceneNode();
	}

	//Destructor
	CSoundSceneNode::~CSoundSceneNode()
	{
	}

	void CSoundSceneNode::addSound(ALbyte* fn)
	{
		ALenum format;
		ALsizei size;
		ALvoid* data;
		ALsizei freq;
		vector<char> buffer;
		ALboolean loop;

		alGenBuffers(1,&bufferID);
		alGenSources(1,&sourceID);

		stringc filename(fn);
		stringc extension;

		getFileNameExtension(extension,filename);

		extension.make_lower();

		if(extension == ".wav")
		{
			alutLoadWAVFile(fn,&format,&data,&size,&freq,&loop);
			alBufferData(bufferID,format,data,size,freq);
			alutUnloadWAV(format,data,size,freq);
		}
		else if(extension == ".ogg")
		{
			int bitStream;
			long bytes;
			char array[BUFFER_SIZE];
			FILE *f;

			f = fopen(fn,"rb");

			if(f == NULL)
			{
				cerr << "Cannot open " << fn << " for reading..." << endl;
				exit(-1);
			}

			vorbis_info *pInfo;
			OggVorbis_File oggFile;

			if(ov_open(f,&oggFile,NULL,0) != 0)
			{
				cerr << "Error opening " << fn << " for decoding..." << endl;
				exit(-1);
			}

			pInfo = ov_info(&oggFile,-1);

			if(pInfo->channels == 1)
				format = AL_FORMAT_MONO16;
			else if(pInfo->channels == 2)
				format = AL_FORMAT_STEREO16;
			else if(pInfo->channels == 4)
				format = alGetEnumValue("AL_FORMAT_QUAD16");
			else if(pInfo->channels == 6)
				format = alGetEnumValue("AL_FORMAT_51CHN16");

			freq = pInfo->rate;

			do
			{
				bytes = ov_read(&oggFile,array,BUFFER_SIZE,0,2,1,&bitStream);

				if(bytes < 0)
				{
					ov_clear(&oggFile);
					cerr << "Error decoding " << fn << "..." << endl;
					exit(-1);
				}

				buffer.insert(buffer.end(),array,array + bytes);
			}
			while(bytes > 0);

			ov_clear(&oggFile);

			alBufferData(bufferID,format,&buffer[0],static_cast<ALsizei>(buffer.size()),freq);
		}

		alSourcei(sourceID,AL_BUFFER,bufferID);
		alSourcef(sourceID,AL_PITCH,1.0f);
		alSourcef(sourceID,AL_GAIN,1.0f);

		cout << "Loaded sound: " << fn << endl;
	}

	void CSoundSceneNode::remove()
	{
		alDeleteSources(1,&sourceID);
		alDeleteBuffers(1,&bufferID);
	}

	void CSoundSceneNode::setParent(ISceneNode* newParent)
	{
		mesh->setParent(newParent);
	}

	void CSoundSceneNode::setPosition(const vector3df& position)
	{
		mesh->setPosition(position);
		alSource3f(sourceID,AL_POSITION,position.X,position.Y,position.Z);
	}

	void CSoundSceneNode::setType(int mode)
	{
		switch(mode)
		{
		case(1):
			alSource3f(sourceID,AL_POSITION,0.0,0.0,0.0);    
			alSource3f(sourceID,AL_VELOCITY,0.0,0.0,0.0);    
			alSource3f(sourceID,AL_DIRECTION,0.0,0.0,0.0);    
			alSourcef (sourceID,AL_ROLLOFF_FACTOR,0.0);
			alSourcei (sourceID,AL_SOURCE_RELATIVE,AL_TRUE);
			break;
		case(2):
			alSource3f(sourceID,AL_POSITION,0.0,0.0,0.0);    
			alSource3f(sourceID,AL_VELOCITY,0.0,0.0,0.0);
			break;
		}
	}


	void CSoundSceneNode::setVolume(float value)
	{
		alSourcef(sourceID,AL_GAIN,value);
	}

	void CSoundSceneNode::setPitch(float value)
	{
		alSourcef(sourceID,AL_PITCH,value);
	}


	void CSoundSceneNode::setPlay()
	{
		alSourcePlay(sourceID);
	}

	void CSoundSceneNode::setStop()
	{
		alSourceStop(sourceID);
	}

	ALuint CSoundSceneNode::getSound()
	{
		return sourceID;
	}

	void CSoundSceneNode::setLoop()
	{
		alSourcei(sourceID,AL_LOOPING,true);
	}

	void CSoundSceneNode::setPause()
	{
		alSourcePause(sourceID);
	}

	void CSoundSceneNode::setRewind()
	{
		alSourceRewind(sourceID);
	}

	void CSoundSceneNode::setReferenceDistance(float value)
	{
		alSourcef(sourceID,AL_REFERENCE_DISTANCE,value);
	}

	void CSoundSceneNode::setRollOff(float value)
	{
		alSourcef(sourceID,AL_ROLLOFF_FACTOR,value);
	}

	void CSoundSceneNode::setName(const char* name)
	{
		mesh->setName(name);
	}

	const char* CSoundSceneNode::getName()
	{
		return mesh->getName();
	}

	void CSoundSceneNode::OnPreRender()
	{
	};

	void CSoundSceneNode::render()
	{
		if(mesh->getParent())
		{
			vector3df position = mesh->getAbsolutePosition();
			alSource3f(sourceID,AL_POSITION,position.X,position.Y,position.Z);
		}
	};

	video::SMaterial& CSoundSceneNode::getMaterial(s32 i)
	{
		return material;
	}

	const core::aabbox3d<f32>& CSoundSceneNode::getBoundingBox() const
	{
		return BBox;
	}