#include "SDL.h"
#include "SDL_mixer.h"
//#include "SDL_sound.h"
#include "sound.h"
#include "stdio.h"
#include "string.h"
#include "stdlib.h"

#include "debug.h"

#ifdef KITSCHY_DEBUG_MEMORY
#include "debug_memorymanager.h"
#endif

#define AUDIO_BUFFER 1024;


bool sound_enabled = false;
Mix_Music *music_sound = 0;
int n_channels = -1;


bool Sound_initialization(void)
{
	if ( -1 == Sound_initialization(0, 0))
		return false;

	return true;
} /* Sound_initialization */


int Sound_initialization(int nc, int nrc)
{
	char SoundcardName[256];
	int audio_rate = 44100;
	int audio_channels = 2;
	int audio_bufsize = AUDIO_BUFFER;
	Uint16 audio_format = AUDIO_S16;
	SDL_version compile_version;
	n_channels = 8;

	sound_enabled = true;
#ifdef F1SPIRIT_DEBUG_MESSAGES

	output_debug_message("Initializing SDL_mixer.\n");
#endif

	if (Mix_OpenAudio(audio_rate, audio_format, audio_channels, audio_bufsize)) {
		sound_enabled = false;
#ifdef F1SPIRIT_DEBUG_MESSAGES

		output_debug_message("Unable to open audio: %s\n", Mix_GetError());
		output_debug_message("Running the game without audio.\n");
#endif

		return -1;
	} 

	SDL_AudioDriverName (SoundcardName, sizeof (SoundcardName));

	Mix_QuerySpec (&audio_rate, &audio_format, &audio_channels);

#ifdef F1SPIRIT_DEBUG_MESSAGES

	output_debug_message("    opened %s at %d Hz %d bit %s, %d bytes audio buffer\n",
	                     SoundcardName, audio_rate, audio_format & 0xFF,
	                     audio_channels > 1 ? "stereo" : "mono", audio_bufsize);

#endif

	MIX_VERSION (&compile_version);

#ifdef F1SPIRIT_DEBUG_MESSAGES

	output_debug_message("    compiled with SDL_mixer version: %d.%d.%d\n",
	                     compile_version.major,
	                     compile_version.minor,
	                     compile_version.patch);

	output_debug_message("    running with SDL_mixer version: %d.%d.%d\n",
	                     Mix_Linked_Version()->major,
	                     Mix_Linked_Version()->minor,
	                     Mix_Linked_Version()->patch);

#endif

	if (nc > 0)
		n_channels = Mix_AllocateChannels(nc);

	if (nrc > 0)
		Mix_ReserveChannels(nrc);

	return n_channels;
} /* Sound_init */

void Sound_release(void)
{
	Sound_release_music();

	if (sound_enabled) {
		//  Sound_Quit();
		Mix_CloseAudio();
	} 

	sound_enabled = false;
} /* Sound_release */


void Stop_playback(void)
{
	if (sound_enabled) {
		Sound_pause_music();
		//  Mix_HookMusic(0, 0);
		Mix_CloseAudio();
		sound_enabled = false;
	} 
} /* Stop_playback */

void Resume_playback(void)
{
	Resume_playback(0, 0);
} /* Resume_playback */


int Resume_playback(int nc, int nrc)
{
	char SoundcardName[256];
	int audio_rate = 44100;
	int audio_channels = 2;
	int audio_bufsize = AUDIO_BUFFER;
	Uint16 audio_format = AUDIO_S16;
	SDL_version compile_version;
	n_channels = 8;

	sound_enabled = true;
#ifdef F1SPIRIT_DEBUG_MESSAGES

	output_debug_message("Initializing SDL_mixer.\n");
#endif

	if (Mix_OpenAudio(audio_rate, audio_format, audio_channels, audio_bufsize)) {
		sound_enabled = false;
#ifdef F1SPIRIT_DEBUG_MESSAGES

		output_debug_message("Unable to open audio: %s\n", Mix_GetError());
		output_debug_message("Running the game without audio.\n");
#endif

		return -1;
	} 

	SDL_AudioDriverName (SoundcardName, sizeof (SoundcardName));

	Mix_QuerySpec (&audio_rate, &audio_format, &audio_channels);

#ifdef F1SPIRIT_DEBUG_MESSAGES

	output_debug_message("    opened %s at %d Hz %d bit %s, %d bytes audio buffer\n",
	                     SoundcardName, audio_rate, audio_format & 0xFF,
	                     audio_channels > 1 ? "stereo" : "mono", audio_bufsize);

#endif

	MIX_VERSION (&compile_version);

#ifdef F1SPIRIT_DEBUG_MESSAGES

	output_debug_message("    compiled with SDL_mixer version: %d.%d.%d\n",
	                     compile_version.major,
	                     compile_version.minor,
	                     compile_version.patch);

	output_debug_message("    running with SDL_mixer version: %d.%d.%d\n",
	                     Mix_Linked_Version()->major,
	                     Mix_Linked_Version()->minor,
	                     Mix_Linked_Version()->patch);

#endif

	if (nc > 0)
		n_channels = Mix_AllocateChannels(nc);

	if (nrc > 0)
		Mix_ReserveChannels(nrc);

	Sound_unpause_music();

	return n_channels;
} /* Resume_playback */


/* a check to see if file is readable and greater than zero */
int file_check(char *fname)
{
	FILE *fp;

	if ((fp = fopen(fname, "r")) != NULL) {
		if (fseek(fp, 0L, SEEK_END) == 0 && ftell(fp) > 0) {
			fclose(fp);
			return true;
		} 

		/* either the file could not be read (==-1) or size was zero (==0) */
#ifdef F1SPIRIT_DEBUG_MESSAGES
		output_debug_message("ERROR in file_check(): the file %s is corrupted.\n", fname);

#endif

		fclose(fp);

		exit(1);
	} 

	return false;
} /* file_check */



SOUNDT Sound_create_sound(char *file)
{
	int n_ext = 6;
	char *ext[6] = {".ogg", ".wav", ".mp3", ".OGG", ".WAV", ".MP3"};
	char name[256];
	int i;

	if (sound_enabled) {
		for (i = 0;i < n_ext;i++) {
			strcpy(name, file);
			strcat(name, ext[i]);

			if (file_check(name)) {
				return Mix_LoadWAV(name);
			}
		} 

#ifdef F1SPIRIT_DEBUG_MESSAGES
		output_debug_message("ERROR in Sound_create_sound(): Could not load sound file: %s.(wav|ogg|mp3)\n", file);

#endif

		exit(1);
	} else {
		return 0;
	} 
} /* Sound_create_sound */


void Sound_delete_sound(SOUNDT s)
{
	if (sound_enabled)
		Mix_FreeChunk(s);
} /* Sound_delete_sound */


void Sound_play(SOUNDT s)
{
	if (sound_enabled)
		Mix_PlayChannel( -1, s, 0);
} /* Sound_play */


void Sound_play(SOUNDT s, int volume)
{
	if (sound_enabled) {
		int channel = Mix_PlayChannel( -1, s, 0);
		Mix_Volume(channel, volume);
	} 
} /* Sound_play */

void Sound_play_ch(SOUNDT s, int ch)
{
	if (sound_enabled && ch < n_channels)
		Mix_PlayChannel(ch, s, 0);
} /* Sound_play_ch */


void Sound_play_ch(SOUNDT s, int ch, int volume)
{
	if (sound_enabled && ch < n_channels) {
		int channel = Mix_PlayChannel(ch, s, 0);
		Mix_Volume(channel, volume);
	} 
} /* Sound_play_ch */

Mix_Music *Sound_create_stream(char *file)
{
	int n_ext = 6;
	char *ext[6] = {".ogg", ".wav", ".mp3", ".OGG", ".WAV", ".MP3"};
	char name[256];
	int i;

	if (sound_enabled) {
		for (i = 0;i < n_ext;i++) {
			strcpy(name, file);
			strcat(name, ext[i]);

			if (file_check(name))
				return Mix_LoadMUS(name);
		} 

#ifdef F1SPIRIT_DEBUG_MESSAGES
		output_debug_message("ERROR in Sound_create_stream(): Could not load sound file: %s.(wav|ogg|mp3)\n", file);

#endif

		exit(1);
	} else {
		return 0;
	} 
} /* Sound_create_stream */


void Sound_create_music(char *f1, int loops)
{
	if (sound_enabled) {
		if (f1 != 0) {
			music_sound = Sound_create_stream(f1);
			Mix_PlayMusic(music_sound, loops);
		} else {
			music_sound = 0;
		} 

		//  playing_music=true;
	} 
} /* Sound_create_music */


bool Sound_file_test(char *f1)
{
	int n_ext = 6;
	char *ext[6] = {".WAV", ".OGG", ".MP3", ".wav", ".ogg", ".mp3"};
	char name[256];
	int i;

	if (sound_enabled) {
		for (i = 0;i < n_ext;i++) {
			strcpy(name, f1);
			strcat(name, ext[i]);

			if (file_check(name))
				return true;
		} 

		return false;
	} else {
		return false;
	} 
} /* Sound_file_test */


void Sound_release_music(void)
{
	if (sound_enabled) {
		//  playing_music=false;
		Mix_HaltMusic();

		if (music_sound != 0)
			Mix_FreeMusic(music_sound);

		music_sound = 0;
	} 
} /* Sound_release_music */



void Sound_pause_music(void)
{
	Mix_PauseMusic();
} /* Sound_pause_music */


void Sound_unpause_music(void)
{
	Mix_ResumeMusic();
} /* Sound_unpause_music */


void Sound_music_volume(int volume)
{
	if (volume < 0)
		volume = 0;

	if (volume > 127)
		volume = 127;

	Mix_VolumeMusic(volume);
} /* Sound_music_volume */
