/*
 * ExNihilo 3D Engine
 * 
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Library General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 * Please read AUTHORS file !!!
 * 
 * $Id: ExManagerSound.cpp,v 1.18 2002/12/13 11:45:01 data Exp $
 *
 */

#include "ExManagerSound.h"

bool ExManagerSound::m_flag = false; 
ExManagerSound* ExManagerSound::m_instance = NULL; 

ExManagerSound* ExManagerSound::CreateSingleton(void){
Guard(ExManagerSound* ExManagerSound::CreateSingleton(void))
	if(!m_flag)
	{
		m_flag = true; // We are creating the error log now, so set flag to true
		m_instance = new ExManagerSound; // Create the error log
	}else
	{
		std::cout<<"Error singleton already created"<<std::endl;
	}
	return m_instance; 
UnGuard
}

ExManagerSound::ExManagerSound (void) 
{
  buffer_index = 0;
  source_index = 0;
  source_available = 0;
  m_initok=false;
}

ExManagerSound::~ExManagerSound (void)
{
	alcDestroyContext (context);
}

void ExManagerSound::Init (void) 
{
Guard (void ExManagerSound::init (void))
	ExManagerObject<ExCSound>::Init();	
	device = alcOpenDevice(NULL);
	if(device == NULL)
	{
		*Consol <<"ExManagerSound:: alcOpenDevice error "<<std::endl;
		return ;
	}
	context=alcCreateContext(device,NULL);
	alcMakeContextCurrent(context);
	//Generate buffers
	alGenBuffers(MAX_BUFFER,buffer);
	if ((error = alGetError()) != AL_NO_ERROR)
	{
		*Consol<<"ExManagerSound:: alGenBuffers error:"<<error<<std::endl;
		return ;
	}
	//Generate sources
	for(int i = 0; i < MAX_SOURCE ; i++)
	{
		alGenSources(1 , &source[i]);
		if ((error = alGetError()) != AL_NO_ERROR)
		{
			*Consol<<"ExManagerSound:: alGenSources error:"<<error<<std::endl;
			return ;
		}
	else source_available++;
	}
	m_initok=true;

	LoadSound("DebutKarminaBas.wav");
	LoadSound("MilieuBas.wav");
	LoadSound("FinKarminaBas.wav");
	
UnGuard
}	

void ExManagerSound::Reset (void)
{
Guard (void ExManagerSound::Reset (void))
	for(m_ItMap=m_Map->begin();m_ItMap!=m_Map->end();m_ItMap++)
	{
		StopSound(m_ItMap->second.GetName());
	}
	ExManagerObject<ExCSound>::Reset();
	LoadSound("DebutKarminaBas.wav");
	LoadSound("MilieuBas.wav");
	LoadSound("FinKarminaBas.wav");
UnGuard
}

void ExManagerSound::DisplayAviableInput (void) {
Guard (void ExManagerSound::DisplayAviableInput (void))
	if(!m_initok)return;
	*Consol<<"****************************************"<<std::endl;
	*Consol<<"* Soundsystem init success             *"<<std::endl;
	*Consol<<"****************************************"<<std::endl;
	*Consol<<"Company        : "<<alGetString (AL_VENDOR)<<std::endl;
	*Consol<<"Version        : "<<alGetString (AL_VERSION)<<std::endl;
	*Consol<<"Renderer       : "<<alGetString (AL_RENDERER)<<std::endl;
	*Consol<<"Extensions     : "<<alGetString (AL_EXTENSIONS)<<std::endl;
	*Consol<<"****************************************"<<std::endl;
UnGuard
}

bool ExManagerSound::LoadSound (std::string file) {
Guard (bool ExManagerSound::LoadSound(std::string file))
  //We check if the file already exist
	//For wav file
	ALsizei     size,freq;
	ALenum	    format;
	ALvoid	    *data;
	 bool found = false;

	for(m_ItMap=m_Map->begin();m_ItMap!=m_Map->end();m_ItMap++)
	{
		if(m_ItMap->second.GetName()==file)
		{
			found = true;
			break;
		}
	}
	if(found)
	{
		*Consol << " ***************************************" << std::endl;
		*Consol << " ** File " << file.c_str() << " already load" << std::endl;
		return -1;
	}
  
  // Load the wav file
	std::string bufferload("../Data/sound/");
	bufferload+=file;
	alutLoadWAVFile((ALbyte*)bufferload.c_str(),&format,&data,&size,&freq,&loop);
	//alutLoadWAVFile((ALbyte*)file.c_str(),&format,&data,&size,&freq,&loop);
  *Consol << " ***************************************" << std::endl;
  *Consol << " ** Loading " << file.c_str() << std::endl;
  *Consol << " - Format " << format << std::endl;
  *Consol << " - Data " << data << std::endl;
  *Consol << " - Size " << size << std::endl;
  *Consol << " - Freq " << freq << std::endl;
  if(loop) *Consol << " - Loop ON";
  else *Consol << " - Loop OFF";

	if ((error = alGetError()) != AL_NO_ERROR)
	{
		*Consol<<"ExManagerSound:: LoadWavFile error:"<<error<<std::endl;
		return -1;
	}
  // Copy wav file into the buffer
	alBufferData(buffer[buffer_index],format,data,size,freq);
	if ((error = alGetError()) != AL_NO_ERROR)
	{
		*Consol<<"ExManagerSound:: alBufferData error:"<<error<<std::endl;
		return -1;
	}
	else
	{
		ExCSound Sound;
		Sound.SetName(file.c_str());
		Sound.SetIdent(buffer_index);
		Add(Sound);
		*Consol << " - ident " << buffer_index << std::endl;
	}

  // Unload the wav file
	alutUnloadWAV(format,data,size,freq);
	if ((error = alGetError()) != AL_NO_ERROR)
	{
		*Consol<<"ExManagerSound:: alutUnloadWAV error:"<<error<<std::endl;
		return -1;
	}

	// Generate source for this wav file
	alSourcei(source[source_index],AL_BUFFER,buffer[buffer_index]);
	if ((error = alGetError()) != AL_NO_ERROR)
	{
		*Consol<<"ExManagerSound:: alSourcei error:"<<error<<std::endl;
		return -1;
	}
  
	source_index++;
	buffer_index++;

	*Consol << " ----> " << file.c_str() << " load ok :-)"  << std::endl;
  


  return true;
	
UnGuard
}

void ExManagerSound::PlaySound (std::string file) {
Guard (void ExManagerSound::PlaySound (std::string file))

	for(m_ItMap=m_Map->begin();m_ItMap!=m_Map->end();m_ItMap++)
	{
		if(m_ItMap->second.GetName()==file)
		{
			alSourcePlay(source[m_ItMap->second.GetIdent()]);
			*Consol<<"Play sound :"<<file<<" ident:"<<m_ItMap->second.GetIdent()<<std::endl;
			if ((error = alGetError()) != AL_NO_ERROR)
			{
				*Consol<<"ExManagerSound:: alSourcePlay error:"<<error<<std::endl;
			}
			return;
		}
	}
UnGuard
}

void ExManagerSound::StopSound (std::string file) {
Guard (void ExManagerSound::StopSound (std::string file))
	for(m_ItMap=m_Map->begin();m_ItMap!=m_Map->end();m_ItMap++)
	{
		if(m_ItMap->second.GetName()==file)
		{
			alSourceStop(source[m_ItMap->second.GetIdent()]);
			*Consol<<"stop sound :"<<file<<" ident:"<<m_ItMap->second.GetIdent()<<std::endl;
			if ((error = alGetError()) != AL_NO_ERROR)
			{
				*Consol<<"ExManagerSound:: alSourcePlay error:"<<error<<std::endl;
			}
			return;
		}
	}
UnGuard
}

void ExManagerSound::PauseSound (std::string file) {
Guard (void ExManagerSound::PauseSound (std::string file))
		for(m_ItMap=m_Map->begin();m_ItMap!=m_Map->end();m_ItMap++)
		{
			if(m_ItMap->second.GetName()==file)
			{
				alSourceStop(source[m_ItMap->second.GetIdent()]);
				*Consol<<"stop sound :"<<file<<" ident:"<<m_ItMap->second.GetIdent()<<std::endl;
				if ((error = alGetError()) != AL_NO_ERROR)
				{
					*Consol<<"ExManagerSound:: alSourcePlay error:"<<error<<std::endl;
				}
				return;
			}
		}
UnGuard
}

void ExManagerSound::SetRepeatSound (std::string file) 
{
Guard (void ExManagerSound::SetRepeatSound (std::string file ))
	for(m_ItMap=m_Map->begin();m_ItMap!=m_Map->end();m_ItMap++)
	{
		if(m_ItMap->second.GetName()==file)
		{
			alSourcei(source[m_ItMap->second.GetIdent()],AL_LOOPING,AL_TRUE);
			*Consol<<"stop sound :"<<file<<" ident:"<<m_ItMap->second.GetIdent()<<std::endl;
			if ((error = alGetError()) != AL_NO_ERROR)
			{
				*Consol<<"ExManagerSound:: alSourcePlay error:"<<error<<std::endl;
			}
			return;
		}
	}
UnGuard
}
int ExManagerSound::GetSound (std::string file) {
Guard (ExCSound* ExManagerSound::GetSound (std::string file))
	return -1;
UnGuard
}

bool ExManagerSound::RemoveSound (std::string file) {
Guard (bool ExManagerSound::RemoveSound (std::string file))
	return true;
UnGuard
}

ExCAction ExManagerSound::InputCommand(ExCCommand Command)
{
Guard(ExCAction ExManagerSound::InputCommand(ExCCommand Command))
	return NOTHING;
UnGuard
}

ExCAction ExManagerSound::InputAction(ExCAction Action)
{
Guard(ExCAction ExManagerSound::InputAction(ExCAction Action))

	switch(Action.m_Action)
	{
	case LIST_SOUND:List();	break;
	case REMOVE_SOUND:RemoveSound(Action.m_Param);break;
	case PLAY_SOUND:PlaySound(Action.m_Param);break;
	case STOP_SOUND:StopSound(Action.m_Param);break;
	case PAUSE_SOUND:PauseSound(Action.m_Param);break;
	case ADD_SOUND:LoadSound(Action.m_Param);break;
	case SET_REPEATS_SOUND:	SetRepeatSound(Action.m_Param);break;
    case GET_REPEATS_SOUND:	//ManagerSound->GetRepeats(Action.m_Param);break;
	
	default:
		*Consol<<"Can not file action in SOUND_ACTION_MAP"<<std::endl;
		break;
	}	

	if(Action.m_NextAction){return *Action.m_NextAction;}
	else{return NOTHING;}
UnGuard
}



