/*
	Welcome back!
	Or so i hope, for if you havent read my comments in the main.cc file
	you should immediately return there and read them before trying to
	comprehend this file, if you have, skip to line 216 now.
*/

namespace rectangle_battle
{
	class game_state_mgr
	{
		private:
		GAME_STATE current_state, next_state;
		game_state *active_state;
		
		rectangle_battle::highscore highscore_list;
		
		public:
		//Ah, its nice to see you ;-). Welcome to the constructor, dear
		//friend, I would love to go into detail, however i fear it would
		//be of no use whatsoever if the workings of this class are not
		//understood, so lets elaborate on those first:
		//Every state of the game, that is, the menu, the versus mode,
		//the highscore display, the highscore entry and the survival mode
		//is defined as a child of an abstract base class called game_state
		//(if you wish to look at it, it is declared in include/game_state.h)
		//basically this mereley defines that every one of those states needs
		//at least two methodes, update and draw. The draw method takes no
		//arguments and returns none, the update method takes a value of the
		//enum GAME_STATE, that is the current state and another one which is
		//the state it should return upon finishing(for example if the player
		//is dead in versus mode ;-)). Thanks to the wonderful magic of
		//polymorphism, this will allow me to work with one pointer to 
		//a game_state throughout the entire class and never worry about
		//their individual implementations.
		//Well, this should be more than enough information to understand
		//what the constructor does and why, so the time to explain it is
		//finally nigh ;-).
		//it initializes the pvr(which i use for the first time, so dont
		//expect my usage to be optimized in the slightest) and depending
		//on the flashroms region it uses eighter pal or ntsc(true is ntsc);
		//after this it plays the intro movie(thanks again to Mike Melanson
		//& Josh PH3NOM Pearson for dreamroq), creates an instance of the
		//main_menu class and starts playing the music(which i called
		//ingame.ogg for some weird reason, despite the lack of any other
		//piece of music in the game. I should really reconsider my naming ;_;).
		//The last action it takes is explained down there and after reading it
		//i suggest you take a look at the extraordinary simple method called
		//draw, which can be found in line 203. Bye.
		game_state_mgr()
		{
			kos_gfx::pvr::init(640,480,flashrom_get_region()==FLASHROM_REGION_US?true:false);
			
			kos_gfx::fmv::init();
				kos_gfx::fmv::play("/rd/fmv/2d_rp.roq");
			kos_gfx::fmv::shutdown();
			
			kos_gfx::sound::init();
			kos_gfx::sound::music::init();
			kos_gfx::input::init();
			
			current_state=MAIN_MENU;
			next_state=MAIN_MENU;
			active_state=new rectangle_battle::main_menu("/rd/images/menu_0.png");

			kos_gfx::sound::music::play("rd/bgm/ingame.ogg");
			
			//Try to find a highscore file ;-);
			for(int i=0;i<4;++i)
			{
				if(highscore_list.load(i))
					break; //Ok, found one, stop searching(yeah, I am a lazy bastard, the user has no means of selecting which one to use(exept for changing the physical vmu location ;-)) ;-));
			};
		};
		
		~game_state_mgr()
		{
			if(active_state!=NULL)
				delete active_state;
			
			kos_gfx::sound::music::stop();
			kos_gfx::sound::music::shutdown();
			kos_gfx::sound::shutdown();
			kos_gfx::input::shutdown();
			kos_gfx::pvr::shutdown();
		};
		
		//So, it has come to this at last. The last unexplained method this
		//strange class has to offer and someone managed to read up to this
		//point without running away in pain and agony. I am proud of you,
		//whoever you are ;-).
		//....
		//Most of the time this does nothing more than calling the
		//collision_mgr::update() function, which manages the collision
		//(one could never guess this from its name, could you?)
		//and calling the update method of the currently active state. 
		//everything beyond line 121 only happens if this state changes
		//and all it actually does is delete the last one and create the new
		//one, with the notable exeptions of the versus mode and the
		//highscore_entry. The first plays a movie showing the triumphant
		//rectangle pilot(thanks again to Mike Melanson&Josh PH3NOM Pearson
		//for dreamroq), whilst the latter is only executed if the player
		//actually managed to archive a highscore.
		//If the game_state_mgr was instructed to quit, that is, the
		//next_state variable equals QUIT, it obeys and returns false;
		//Thats it, thats all there is to know about this file and if you
		//are as wise as i believe you to be, you will stop your exploration
		//right now, for i cannot guarantee your sanity otherwise.
		//However if your will is really that strong and you deem my rants
		//aweful enough, you may continue in include/main_menu.h
		bool update()
		{
			rectangle_battle::collision_mgr::update();
			
			GAME_STATE next;
			if(active_state!=NULL)
				next=active_state->update(current_state,next_state);
			else
				next=MAIN_MENU;
			
			if(next!=current_state)
			{
				delete active_state;
				active_state=NULL;
				
				//play victory fmvs ;-);
				if(current_state==VERSUS_MODE && (versus_mode::blue_won || versus_mode::red_won))
				{
					kos_gfx::sound::music::stop();
					kos_gfx::sound::music::shutdown();
					thd_sleep(100);
					kos_gfx::fmv::init();
						kos_gfx::fmv::play(versus_mode::red_won?"/rd/fmv/red_wins.roq":"/rd/fmv/blue_wins.roq");
					kos_gfx::fmv::shutdown();
					kos_gfx::sound::init();
					kos_gfx::sound::music::init();
					kos_gfx::sound::music::play("/rd/bgm/ingame.ogg");
				};
				
				current_state=next;
				switch(current_state)
				{
					case MAIN_MENU:
					{
						rectangle_battle::rectangle::points=0;
						
						active_state=new main_menu("/rd/images/menu_0.png");
						next_state=MAIN_MENU;
						break;
					};
					case VERSUS_MODE:
					{
						active_state=new versus_mode("/rd/images/ingame_0.png","/rd/images/ingame_1.png",rectangle_battle::main_menu::p1_id,rectangle_battle::main_menu::p2_id);
						next_state=MAIN_MENU;
						break;
					};
					case SURVIVAL_MODE:
					{
						rectangle_battle::rectangle::points=0;
						
						active_state=new survival_mode("/rd/images/ingame_0.png","/rd/images/ingame_1.png",rectangle_battle::main_menu::p1_id);
						next_state=HIGHSCORE_ENTRY;
						break;
					};
					//It is important that those two states follow right after each other, for HIGHSCORE_ENTRY relies upon this fact to pass its execution on in case it is not needed ;-);
					case HIGHSCORE_ENTRY:
					{
						if(highscore_list.is_highscore(rectangle_battle::rectangle::points))
						{
							active_state=new highscore_entry("/rd/images/menu_1.png",&highscore_list,rectangle_battle::main_menu::p1_id);
							next_state=HIGHSCORE_DISPLAY;
							break;
						}
						else
							current_state=HIGHSCORE_DISPLAY;
					};
					case HIGHSCORE_DISPLAY:
					{	
						//Load the last used highscore file or try to find another one if this fails ;-)
						if(!highscore_list.load())
						{
							for(int i=0;i<4;++i)
							{
								if(highscore_list.load(i))
									break;
							};
						};
						
						active_state=new highscore_display("/rd/images/menu_0.png", &highscore_list);
						next_state=MAIN_MENU;
						break;
					};
					case QUIT:
					{
						return false;
					};
				};
			};
			
			return true;
		};
		
		//Quite simple, didnt i tell you? If there is an active state,
		//the draw method is called, thats about all there is to it
		//polymorphism is really awesome, dont you agree?
		//well, I propose you have a look at the update method next. 
		//it can be found in line 88.
		void draw()
		{
			kos_gfx::pvr::begin_drawing();
				if(active_state!=NULL)
					active_state->draw();
			kos_gfx::pvr::end_drawing();
		};
		
		//Hi there ;-). Congratulations on coming this far, here is a
		//small reward:
		//QKVX8-WQX7R-P2BC9-JWG6Q-BWKGY
		//If you are the first one to find this, this token will allow
		//you or a friend of yours or anyone of your choice to download
		//the Xbox version of RectangleBattle free of charge ;-).
		//Well, nonetheless, allow me to introduce the next piece of code ;-)
		//This mereley calls the update method repeatedly and if it is not
		//finished(which it will indicate by returning false), the input
		//(that is the controllers state) will be updated and the draw method
		//is called. Due to the latter being far more simple and far more easy
		//to explain I would suggest you read it next, however I almost
		//forgot to explain the constructor, so jump up to line 19 and
		//I will continue to annoy you with my meaningless and all too long
		//speeches(which can hardly be called explanations).
		void run()
		{
			while(update())
			{
				kos_gfx::input::update();
				draw();
			};
		}; 
	};
};
