// BlinkenSisters - Hunt for the Lost Pixels
//     Bringing back the fun of the 80s
//
// (C) 2005-07 Rene Schickbauer, Wolfgang Dautermann
//
// See License.txt for licensing information
//


#include <stdlib.h>
#include "globals.h"
#include "sound.h"
#include "errorhandler.h"


int audio_rate = 44100;
Uint16 audio_format = AUDIO_S16; /* 16-bit stereo */
int audio_channels = 2;
Uint32 audio_buffers = AUDIOBUFFERSIZE;
extern bool soundOK ;
bool soundInitOK = false;
char bgMusicFile[1000];

#ifndef DISABLE_SOUND
Mix_Music *levelMusic = NULL;
Mix_Chunk *sound_fx[FX_MAX_PREDEF + MAX_FX_SAMPLES];
Mix_Chunk *sound_fx_video = 0;
Uint32 sndfxcnt = 0;
#endif
bool playOnceFinished = false;
bool onlyPlayOnce = true;
Uint32 soundSimTick = 0; // Simulated sound length if we have no sound

void initSound()
{
	if (soundOK==false) { return ; } // Sound support not compiled or disabled by command line switch -s
#ifndef DISABLE_SOUND
	/* This is where we open up our audio device.  Mix_OpenAudio takes
	as its parameters the audio format we'd /like/ to have. */
	if(Mix_OpenAudio(audio_rate, audio_format, audio_channels, audio_buffers)) {
		printf("Unable to open audio!\n");
		soundInitOK = false;
		return;
	} else {
		soundInitOK = true;
		Mix_HookMusicFinished(soundMusicFinished);
	}
	
	/* If we actually care about what we got, we can ask here.  In this
	program we don't... yet */
	Mix_QuerySpec(&audio_rate, &audio_format, &audio_channels);
	sound_fx[FX_COLLECT_PIXEL] = Mix_LoadWAV(configGetPath("fx_collect_pixel.ogg"));
	sound_fx[FX_KILL_MONSTER] = Mix_LoadWAV(configGetPath("fx_kill_monster.ogg"));
	sound_fx[FX_KILL_PLAYER] = Mix_LoadWAV(configGetPath("fx_killed.ogg"));
	sound_fx[FX_LEVEL_FINISHED] = Mix_LoadWAV(configGetPath("fx_level_finished.ogg"));
	sound_fx[FX_MENU] = Mix_LoadWAV(configGetPath("fx_menu.ogg"));
	sound_fx[FX_RESPAWNPOINT] = Mix_LoadWAV(configGetPath("fx_respawnpoint.ogg"));
#endif // DISABLE_SOUND
}

void deInitSound()
{
	printf("De-init sound\n");
	if(!soundOK || !soundInitOK) {
		return;
	}
#ifndef DISABLE_SOUND
	soundStopMusic();
	levelMusic = NULL;
	
	Mix_FreeChunk(sound_fx[FX_COLLECT_PIXEL]);
	Mix_FreeChunk(sound_fx[FX_KILL_MONSTER]);
	Mix_FreeChunk(sound_fx[FX_KILL_PLAYER]);
	Mix_FreeChunk(sound_fx[FX_LEVEL_FINISHED]);
	Mix_FreeChunk(sound_fx[FX_MENU]);
	
	deInitSoundFXLua();
	
	Mix_CloseAudio();
	soundInitOK = false;
#endif // DISABLE_SOUND
}


void soundPlayFX(Uint32 fx) {
	if(!soundOK || !soundInitOK) {
		return;
	}
#ifndef DISABLE_SOUND	
	Mix_PlayChannel(-1, sound_fx[fx], 0);
#endif // DISABLE_SOUND
}


void soundStartMusic(const char* fname, bool playOnce)
{
	// There are some things that ALWAYS needs to be done, no matter if sound actually works
	soundStopMusic(); // Has his own checks and simulated to-do list
	playOnceFinished = false;
	onlyPlayOnce = playOnce;
	
	if(!soundOK || !soundInitOK) {
		soundSimTick = SDL_GetTicks() + 45000; // Simulated sound plays 45 seconds
		return;
	}
#ifndef DISABLE_SOUND	
	
	
	sprintf(bgMusicFile, "%s", fname); // Remember original Filename
	
	char fullfname[MAX_FNAME_LENGTH];
	sprintf(fullfname, "%s", configGetPath(fname));
	levelMusic = Mix_LoadMUS(fullfname);	
	if(!levelMusic) {
		DIE(ERROR_SOUND_READ, fullfname);
	}
	/*
	if(!playOnce) {
		Mix_PlayMusic(levelMusic, -1);
	} else {
		Mix_PlayMusic(levelMusic, 1);
	}
	 We do NOT use automated repeat - we do it ourself to try and fix a bug
	 */
	Mix_PlayMusic(levelMusic, 1);
	

	Mix_VolumeMusic(MIX_MAX_VOLUME / 2);
#endif // DISABLE_SOUND	
}

void soundStopMusic()
{
	// There are some things that ALWAYS needs to be done, no matter if sound actually works
	playOnceFinished = false;
	onlyPlayOnce = false;
	
	if(!soundOK || !soundInitOK) {
		soundSimTick = 0;
		return;
	}
#ifndef DISABLE_SOUND	
	Mix_HaltMusic();
	if(levelMusic) {
		Mix_FreeMusic(levelMusic);
		levelMusic = 0;
	}

#endif // DISABLE_SOUND
}

Uint32 addSoundFXLua(char* fname) {
	if(!soundOK || !soundInitOK) {
		return 0;
	}
#ifndef DISABLE_SOUND	
	char fullfname[MAX_FNAME_LENGTH];
	sprintf(fullfname, "%s", configGetPath(fname));

	if(sndfxcnt >= MAX_FX_SAMPLES) {
		DIE(ERROR_BOUNDARY, "too many FX samples");
	}
	sound_fx[sndfxcnt + FX_MAX_PREDEF] = Mix_LoadWAV(fullfname);
	if(!sound_fx[sndfxcnt + FX_MAX_PREDEF]) {
		DIE(ERROR_SOUND_READ, fname);
	}
	sndfxcnt++;
	return (sndfxcnt-1);
#else // DISABLE_SOUND
	return 0 ;
#endif // DISABLE_SOUND
}

void soundPlayFXLua(Uint32 fx) {
	if(!soundOK || !soundInitOK) {
		return;
	}
#ifndef DISABLE_SOUND	
	if(fx >= sndfxcnt) {
		DIE(ERROR_INDEX_INVALID, "Unknown sample");
	}
	soundPlayFX(fx + FX_MAX_PREDEF);
#endif // DISABLE_SOUND
}

void initSoundFXLua() {
	if(!soundOK || !soundInitOK) {
		return;
	}
#ifndef DISABLE_SOUND
	sndfxcnt = 0;
#endif // DISABLE_SOUND
}

void deInitSoundFXLua() {
	if(!soundOK || !soundInitOK) {
		return;
	}
#ifndef DISABLE_SOUND	
	for(Uint32 i = 0; i < sndfxcnt; i++) {
		Mix_FreeChunk(sound_fx[i + FX_MAX_PREDEF]);
	}
	sndfxcnt = 0;
#endif // DISABLE_SOUND
}

void soundStartVideoFX(SDL_RWops* src) {
	if(!soundOK || !soundInitOK) {
		return;
	}
#ifndef DISABLE_SOUND	
	sound_fx_video=Mix_LoadWAV_RW(src, 0);
	if(!sound_fx_video) {
		printf("Couldn't start video sound\n");
		return;
	}
	Mix_PlayChannel(-1, sound_fx_video, 0);
#endif // DISABLE_SOUND
}

void soundStopVideoFX() {
	if(!soundOK || !soundInitOK) {
		return;
	}
#ifndef DISABLE_SOUND
	if(!sound_fx_video) {
		return;
	}
	Mix_FreeChunk(sound_fx_video);
	sound_fx_video = 0;
#endif // DISABLE_SOUND
}

void soundMusicFinished() {
	if(onlyPlayOnce) {
		soundStopMusic();
		playOnceFinished = true;
	} else {
		// soundStartMusic auto-unloads current file, so we don't have to call
		// it explicitely
		soundStartMusic(bgMusicFile, false);
	}
}

bool soundPlayOnceFinished() {
	if(!soundOK || !soundInitOK) {
		// Simulate playonce
		if(soundSimTick != 0 && SDL_GetTicks() > soundSimTick) {
			if(onlyPlayOnce) {
				playOnceFinished = true;
			}
		}
	}
	return playOnceFinished;
}

