/*
* This code is released under the GNU General Public License.  See COPYING for 
* details.  Copyright 2003 John Spray: spray_john@users.sourceforge.net
*/

#include <SDL.h>
#include <SDL_main.h>
#include <SDL_ttf.h>
#include <physfs.h>
#include <string>
using namespace std;
#include "Game.h"
#include "Config.h"

#include "Visual.h"
#include "SoundCore.h"
#include "Menu.h"

#include "ScoreBoard.h"

Config GLOB_conf;
ScoreBoard GLOB_scores;

int main(int argc,char* argv[])
{
	int mainquit=0;
	string iconpath;
	string iconfile;

	PHYSFS_init(argv[0]);

	//set up all the filesystem stuff:
	#ifdef WIN32
	string homepath=getenv("USERPROFILE");
	#else
	string homepath=getenv("HOME");
	#endif
	string configpath=homepath+"/.excido";
//	string datapath="./data";
	string datapath=DATADIR;

	if(!PHYSFS_addToSearchPath(homepath.c_str(),0))
					printf(	"main: PHYFS_addToSearchPath failed! %s\n",
									PHYSFS_getLastError());
	if(!PHYSFS_setWriteDir(homepath.c_str()))
					printf(	"main: PHYFS_setWriteDir failed! %s\n",
									PHYSFS_getLastError());
	if(!PHYSFS_exists(".excido")){
		printf("Creating .excido directory in %s\n",homepath.c_str());
		PHYSFS_mkdir(".excido");
	}
	if(!PHYSFS_removeFromSearchPath(homepath.c_str())) printf("main: PHYFS_removeFromSearchPath failed! %s\n",PHYSFS_getLastError());

	if(!PHYSFS_setWriteDir(NULL))
					printf("main: PHYFS_setWriteDir failed! %s\n",PHYSFS_getLastError());

	if(!PHYSFS_addToSearchPath(configpath.c_str(),0))
					printf(	"main: PHYFS_addToSearchPath failed on '%s'! %s\n",
									configpath.c_str(),PHYSFS_getLastError());
	/*append the data directory to the search list.  We want the contents 
	 * of configpath to have precedence over the contents of the data directory*/
	if(!PHYSFS_addToSearchPath(datapath.c_str(),1)) printf("main: PHYFS_addToSearchPath failed on '%s'! %s\n",datapath.c_str(),PHYSFS_getLastError());	
	
	if(!PHYSFS_setWriteDir(configpath.c_str())) printf("main: PHYFS_setWriteDir failed! %s\n",PHYSFS_getLastError());

	//load the configuration data
	GLOB_conf.Load("excido.conf");
	//override file-configuration with any command line options
	if(GLOB_conf.ParseArgs(argc,argv)){
		PHYSFS_deinit();
		return -1;
	}

	//load the high-score table
	GLOB_scores.Load("excido.scores");


	if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)){
		printf("main: SDL initialisation failed with error %s\n",SDL_GetError());
		PHYSFS_deinit();
		return -1;
	}

	SDL_WM_SetCaption("excido","excido");
	#ifdef RELEASE
	SDL_ShowCursor(SDL_DISABLE);
	#endif
	iconpath=DATADIR;
	iconfile="wmicon.bmp";
	iconfile=iconpath+iconfile;
	SDL_WM_SetIcon(SDL_LoadBMP(iconfile.c_str()), NULL);

	//we'll setvideomode later, inside the menu loop, so that when it loops
	//after the user has been in the configuration menu, any changes to video
	//settings are properly reflected
	int sdlvidflags=SDL_OPENGL | SDL_RESIZABLE;
	SDL_Surface* screen;
	
	//Initialise SDL_ttf
	if(TTF_Init()){
		printf("main: TTF_Init failed!\n");
		PHYSFS_deinit();
		SDL_Quit();
		return -1;
	}

	alutInit(0,NULL);
	fprintf(stderr,"SoundCore::SoundCore: OpenAL initialised\n");fflush(stderr);
	
	//for the menu system
	Game* menugame;
	Visual* menuvisual;
	SoundCore* menusound;
	Menu* menu;
	menufunc retval;
	Vector vzero; //For SoundCore's benefit
	vzero=0.0f;

	//Hell, why not just use gotos and admit the filthyness of this next part?
	//I hope you follow illogic well, and can predict arcane return value systems
	while(!mainquit){
		while(!GLOB_conf.skipmenu){
			if(GLOB_conf.fullscreen)
				sdlvidflags |= SDL_FULLSCREEN;
			else if(sdlvidflags & SDL_FULLSCREEN)
				sdlvidflags ^= SDL_FULLSCREEN;
			screen=SDL_SetVideoMode(GLOB_conf.screenx,GLOB_conf.screeny,GLOB_conf.bpp,sdlvidflags);

			menugame = new Game(screen);
			menuvisual = new Visual(menugame);
			menusound = new SoundCore();
			menuvisual->InitGL();
			menuvisual->LoadTexture("menuback.png");
			menuvisual->LoadTexture("menucursor.png");
			menusound->LoadSample("menuambient.wav");
			menusound->Play("menuambient.wav",-1,vzero,vzero);

			char* labels[]={"Play","Configure","High Scores","Exit",NULL};
			menufunc functions[]={MENU_CONTINUE,MENU_SUB1,MENU_SUB2,MENU_QUITFULL};
			void* targets[]={NULL,NULL,NULL,NULL};
			menu=new Menu(labels,functions,targets,menuvisual);
			menu->solidbackground=1;
			retval=menu->Happen();
			delete menu;

			if(retval==MENU_QUITFULL){
				delete menuvisual;
				delete menusound;
				delete menugame;
				GLOB_conf.Dump("excido.conf");
				GLOB_scores.Dump("excido.scores");
				PHYSFS_deinit();
				TTF_Quit();
				SDL_Quit();
				return 0;
			}
			else if(retval==MENU_SUB1){
				GLOB_conf.ConfigMenu(menuvisual,menusound);
			}
			else if(retval==MENU_SUB2){
				GLOB_scores.Display(menuvisual);
			}
			else if(retval==MENU_CONTINUE)
				GLOB_conf.skipmenu=1;

			delete menusound;
			delete menuvisual;
			delete menugame;
		}
		GLOB_conf.skipmenu=0;
		//the whole skipmenu thing isn't too readable.  Basically, the user can set it using
		// "-s", but it's also used internally to handle the situation where this menu returns,
		//but we're launching the ConfigMenu, so we want to loop around again.  You get it.

		if(GLOB_conf.fullscreen)
			sdlvidflags |= SDL_FULLSCREEN;
		else if(sdlvidflags & SDL_FULLSCREEN)
			sdlvidflags ^= SDL_FULLSCREEN;
		screen=SDL_SetVideoMode(GLOB_conf.screenx,GLOB_conf.screeny,GLOB_conf.bpp,sdlvidflags);

		Game* game = new Game(screen);
		game->verbose=GLOB_conf.verbose;
		mainquit=game->Happen();
		delete game;
	

		if(mainquit==1) mainquit=0; 
		//could use temp variable for extra clarity, but you get it
		//game::Happen has to return 2 to actually get out.  QUITFULL

	} //mainquit

	alutExit();

	GLOB_conf.Dump("excido.conf");
	GLOB_scores.Dump("excido.scores");
	PHYSFS_deinit();
	TTF_Quit();
	SDL_Quit();
	return 0;
}
