/*
Copyright (c) 2000-2001 Olivier Dagenais

This software is provided 'as-is', without any express or implied warranty. In
no event will the authors be held liable for any damages arising from the use
of this software.

Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:

1. The origin of this software must not be misrepresented; you must not claim
that you wrote the original software. If you use this software in a product,
an acknowledgment in the product documentation would be appreciated but is not
required.

2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.

3. This notice may not be removed or altered from any source distribution.
*/

#include <stdlib.h>
#include <stdio.h>

#ifdef WIN32
#include <windows.h>
#endif
#include "dep/glew/include/gl/glew.h"
#include "SDL.h"
#include "SDL_mixer.h"
#include "SDL_config.h"
#include "GopherTypes.h"
#include "GopherLoader.h"
#include "GopherCore.h"
#include "GopherLoading.h"


int main ( int argc, char * argv [ ] )
{
	unsigned long howFar = 0;
	DemoStruct actualDemo;
	SDL_Config_Struct config;
	SDL_Surface * screen;
	Mix_Music * demoMusic = NULL;

	try
	{
		GopherLoadDemoFromXML ( argv[1], actualDemo );
		howFar = 1;

		// Initialize SDL by reading options from ".\SDL.ini"
		SDL_Config_DefaultConfig ( &config );
		config.subSystems = SDL_INIT_TIMER | SDL_INIT_VIDEO;
		config.subSystems = SDL_INIT_TIMER | SDL_INIT_VIDEO | SDL_INIT_AUDIO;
		if ( SDL_Config_LoadConfig ( "SDL.ini", &config ) < 0 )
		{
			throw 0;
		}

		if ( actualDemo.useOpenGL )
		{
			//config.videoFlags |= SDL_OPENGLBLIT;
			config.videoFlags |= SDL_OPENGL;
		}
		if ( ( screen = SDL_Config_Init ( &config ) ) == NULL )
		{
			throw 0;
		}
		howFar = 2;

		// Display "Loading" picture
		if ( loadLoadingPicture ( config, screen, actualDemo.useOpenGL ) < 0 )
		{
			throw 0;
		}
		//SDL_Delay ( 1000 );

		// Initialize GLUT

		GLenum err = glewInit();
		if (GLEW_OK != err)
		{
			throw 0;
		}

		// Initialize libraries
		if ( initializeLibraries ( actualDemo ) < 0 )
		{
			throw 0;
		}
		howFar = 3;

		//	Match function pointers to all event instances
		if ( matchFunctionPointers ( actualDemo ) < 0 )
		{
			throw 0;
		}
		howFar = 4;

		// Create the inputSurfaces and the outputSurfaces
		actualDemo.numOutputSurfaces = 2;
		if ( createSurfaces ( actualDemo, config, screen ) < 0 )
		{
			throw 0;
		}
		howFar = 5;

		// Call Gopher_Init in all libraries
		if ( gopherInitialize ( actualDemo ) < 0 )
		{
			throw 0;
		}
		howFar = 6;

		// Load music file
		if ( config.subSystems & SDL_INIT_AUDIO )
		{
			demoMusic = Mix_LoadMUS ( actualDemo.musicFile );
			if ( demoMusic == NULL )
			{
				//throw 0;
			}
		}
		howFar = 7;

		// Start timer, rendering thread, etc..
		// UNDONE:  Introduce this stuff after we get an "as fast as possible" version
		// working nicely.
		howFar = 8;

		// Start music
		Uint32 startOffset = 0;
		Uint32 Volume = 128;
		if ( argc > 2 )
			startOffset = atoi ( argv[2] );
		if ( argc > 3 )
			Volume = atoi ( argv[3] );

		if ( config.subSystems & SDL_INIT_AUDIO ) 
		{
			Mix_PlayMusic ( demoMusic, 0 );
			if ( Mix_GetMusicType(NULL) != MUS_OGG)
				startOffset = 0;
			else 
				Mix_SetMusicPosition ( startOffset / 1000.0 );

			Mix_VolumeMusic(Volume);
		}

		howFar = 9;

		// Play the demo
		if ( gopherPlay ( actualDemo, screen, startOffset ) < 0 )
		{
			throw 0;
		}
	}
	catch ( ... )
	{
		fprintf ( stderr, "Something went horribly wrong.  Stopped at step '%d'.\n", howFar );
		SDL_Delay ( 1000 );
	}


	switch ( howFar )
	{
		case 9:
			// Stop the music
			Mix_HaltMusic ( );
		case 8:
			// Destroy rendering thread
		case 7:
			// Unload music file
			Mix_FreeMusic ( demoMusic );
		case 6:
			// Call Gopher_Quit in all libraries
			gopherTerminate ( actualDemo );
		case 5:
			// Destroy both the inputSurfaces and the outputSurfaces
			destroySurfaces ( actualDemo );
		case 4:
			// Free function pointers
			// (no op - they don't need to be freed)
		case 3:
			// Free libraries
			freeLibraries ( actualDemo );
		case 2:
			// Uninitialize SDL
			// BUG:  If I don't Quit SDL (Audio), the operating system seems
			// to take care of it for me and I hence do not run into the
			// race condition
			//SDL_Config_Quit ( );
		case 1:
			// destroy the demo and deallocate everything
			destroyDemo ( actualDemo );
			break;
	}

	if ( howFar == 9 )
	{
		return ( 0 );
	}
	else
	{
		return ( 1 );
	}
}


