#include "SDL/SDL.h"
#include "SDL/SDL_image.h"
#include "SDL/SDL_ttf.h"
#include "SDL/SDL_mixer.h"


#include "functions/surfaces.hpp"
#include "functions/loading.hpp"
#include "timer/timer.hpp"

#include <sstream>

#include "map/map.hpp"

#include "characters/ridinghood.hpp"
#include "characters/enemy.hpp"

#include "effects/effects.hpp"
#include "soundeffecter/soundeffecter.hpp"

#include "items/candle.hpp"
#include "items/flower.hpp"
#include "items/apple.hpp"

#include "menu/menu.hpp"

#include "instructions/instructions.hpp"

//GLOBAL VARIABLES
SDL_Surface* screen = NULL;

//Timer
TIMER* myTimer;

//Objects
map* myMap;
ridinghood* myRidingHood;
enemy* myEnemy;

//Effects
effects* myEffects;
soundeffecter *mySoundEffects;

//ITEMS
candles* myCandles;
apples*  myApples;
flowers* myFlowers;

//Menu
menu* myMenu;

//Instructions
instructions* myInstructions;

//Difficulty
const bool EASY = true;
const bool HARD = false;

bool Difficulty = EASY;

void Init_Variables(){

	myMap = new map;

	//Timer
	myTimer = new TIMER;
	//Menu
	myMenu = new menu;
	myInstructions = new instructions;
	//Effects
	myEffects = new effects;
	mySoundEffects = new soundeffecter;

	//ITEMS
	myCandles = new candles;
	myApples  = new apples;
	myFlowers = new flowers;
	//Objects
	myRidingHood = new ridinghood;
	myEnemy = new enemy;


}

void Delete_Variables(){

	//Deleting Menu
	delete myMenu;
	delete myInstructions;
	//Deleting Timer
	delete myTimer;
	//Deleting effects
	delete myEffects;
	delete mySoundEffects;




	//Deleting Objects
	delete myMap;
	delete myRidingHood;
	delete myEnemy;
	//Deleting Items
	delete myCandles;
	delete myFlowers;
	delete myApples;

}

void Restart(){

	delete myMap;
	delete myRidingHood;
	delete myEnemy;

	delete myCandles;
	delete myFlowers;
	delete myApples;

	delete myInstructions;

	myMap = new map;
	myRidingHood = new ridinghood;
	myEnemy = new enemy;

	myCandles = new candles;
	myFlowers = new flowers;
	myApples = new apples;

	myInstructions = new instructions;

}

const int FRAMES_PER_SECOND = 25;


void show_tutorials(){

	if( myInstructions->Tutorial( screen, TUT_CANDLE ) ) myRidingHood->NullVel();
	if( myInstructions->Tutorial( screen, TUT_APPLE ) ) myRidingHood->NullVel();

	if( myRidingHood->getApples() ){
		if( myInstructions->Tutorial( screen, TUT_EAT ) ) myRidingHood->NullVel();
	}

	if( myRidingHood->getCandles() ){
		if( myInstructions->Tutorial( screen, TUT_LIGHT ) ) myRidingHood->NullVel();
	}

	if( myRidingHood->getFlowers() == 6 ){
		if( myInstructions->Tutorial( screen, TUT_END ) ) myRidingHood->NullVel();
	}

	if( myEnemy->isTriggered() ){
		if( myInstructions->Tutorial( screen, TUT_ENEMY ) ) myRidingHood->NullVel();
	}

	if( myMap->isBigFogCollision() ){
		if( myInstructions->Tutorial( screen, TUT_BIGFOG ) )myRidingHood->NullVel();
	}

	if( myFlowers->isFound() ){
		if( myInstructions->Tutorial( screen, TUT_FLOWER ) )myRidingHood->NullVel();
	}

}

void show_book(){

	if( myInstructions->show( screen, TUT_INTRO ) )
		myRidingHood->NullVel();

	switch( myRidingHood->getFlowers() ){

		case 1 : if( myInstructions->show( screen, TUT_FLOWER1 ) ) myRidingHood->NullVel(); break;
		case 2 : if( myInstructions->show( screen, TUT_FLOWER2 ) ) myRidingHood->NullVel(); break;
		case 3 : if( myInstructions->show( screen, TUT_FLOWER3 ) ) myRidingHood->NullVel(); break;
		case 4 : if( myInstructions->show( screen, TUT_FLOWER4 ) ) myRidingHood->NullVel(); break;
		case 5 : if( myInstructions->show( screen, TUT_FLOWER5 ) ) myRidingHood->NullVel(); break;
		case 6 : if( myInstructions->show( screen, TUT_FLOWER6 ) ) myRidingHood->NullVel(); break;
	}

}

void Logo(){

	SDL_Surface* logo = load_image( "menu/logo.jpg" );
	int Alpha = 0;
	TIMER LogoTimer;
	TIMER FpsTimer;

	LogoTimer.start();
	while( LogoTimer.get_ticks() < 5000 ){
		FpsTimer.start();

		SDL_SetAlpha( logo, SDL_SRCALPHA, Alpha );
		Alpha += 1;
		apply_surface( 0, 0, logo, screen );

		SDL_Flip( screen );

		if( FpsTimer.get_ticks() < 1000 / 25 )
			SDL_Delay( 1000 / 25 - FpsTimer.get_ticks() );

	}

	SDL_FreeSurface( logo );

}

int main( int argc, char** argv ){

	SDL_Init( SDL_INIT_EVERYTHING );
	screen = SDL_SetVideoMode( 800, 600, 32, SDL_SWSURFACE | SDL_FULLSCREEN );
	SDL_ShowCursor( SDL_DISABLE );

	Logo();

	//Initialising Variables
	show_loading( screen );
	TTF_Init();

	Mix_OpenAudio( 22050, MIX_DEFAULT_FORMAT, 2, 4096 );

	Init_Variables();

	SDL_Event event;
	bool quit = false;
	bool mainquit = false;

	Mix_Music* myMusic = Mix_LoadMUS( "sounds/music.wav" );
	Mix_Music* myMenuMusic = Mix_LoadMUS( "sounds/menumusic.wav" );

	Mix_Chunk* Die = Mix_LoadWAV( "sounds/rdie.wav" );

	Mix_PlayMusic( myMenuMusic, -1 );
	while( !mainquit ){


		myTimer->start();

		myMenu->deselect();

		while( SDL_PollEvent( &event ) ){

			myMenu->handle_event( event, Difficulty );

		}

		myMenu->show( screen, Difficulty );

		if( myMenu->selectedmenu() == -1 ){
			if( Mix_PlayingMusic() == 0 )
				Mix_PlayMusic( myMenuMusic, -1 );
		}
		if( myMenu->selectedmenu() == 0 ){
			Mix_HaltMusic();
			Mix_PlayMusic( myMusic, -1 );
		}

		//Credits
		if( myMenu->selectedmenu() == 3 ) myMenu->credits( screen );
		//Help
		if( myMenu->selectedmenu() == 2 ) myMenu->help( screen );

		//GAMESTART
		while( !quit && myMenu->selectedmenu() == 0 ){

		show_book();

		myTimer->start();

			while( SDL_PollEvent( &event ) ){
				if( event.type == SDL_KEYDOWN )
					switch( event.key.keysym.sym ){

						case SDLK_ESCAPE : quit = true; break;

						default : break;

					}

				myRidingHood->handle_event( event, Difficulty );

			}

			myRidingHood->refresh( Difficulty );
			mySoundEffects->play();

			//Moving enemies
			myEnemy->move( myRidingHood->getXVel(), myRidingHood->getYVel(), myMap->isCollision(), myRidingHood->getHP(), myRidingHood -> isExtraLightOn(), Difficulty );

			//Moving world
			myMap->move( myRidingHood->getXVel(), myRidingHood->getYVel(), myRidingHood->getFlowers() );
			//Moving effects
			myEffects->move( myRidingHood->getXVel(), myRidingHood->getYVel(), myMap->isCollision() );
			//Moving Items
			myCandles->move( myRidingHood->getXVel(), myRidingHood->getYVel(), myMap->isCollision() );
			myFlowers->move( myRidingHood->getXVel(), myRidingHood->getYVel(), myMap->isCollision(), myRidingHood->isLightOn(), myRidingHood->isExtraLightOn() );
			myApples->move( myRidingHood->getXVel(), myRidingHood->getYVel(), myMap->isCollision() );


			//Collecting Items
			myCandles->collect( myRidingHood->getCandles() );
			myFlowers->collect( myRidingHood->getFlowers() );
			myApples->collect( myRidingHood->getApples() );


			//Show world with ridinghood
			myMap->show( screen, myRidingHood->getSpriteSheet(), myRidingHood->getFrame(),
						 myFlowers->getSheet(), myFlowers->getOffset(), myFlowers->getCoords(), myFlowers->getFrame(),
						 myCandles->getSheet(), myCandles->getCoords(), myCandles->getIsOut(), myCandles->getOffsets(), myCandles->getFrame(),
						 myApples->getSheet(), myApples->getIsOut(), myApples->getCoords(),
						 myEffects->getBigFogH(), myEffects->getBigFogV(), myEffects->getBigFogCorner(), myEffects->getXH(), myEffects->getYH(), myEffects->getXV(), myEffects->getYV(), myEffects->getXC(), myEffects->getYC(),
						 myEffects->getBigFogCornerUR(), myEffects->getBigFogCornerDR(), myEffects->getBigFogCornerDL(), myEffects->getBigFogHF(), myEffects->getBigFogVF() );

			//Showing enemies
			myEnemy->show( screen, myRidingHood->isLightOn(), myRidingHood->isExtraLightOn() );

			//Show effects
			myEffects->show( screen, myRidingHood->isLightOn(), myRidingHood->isExtraLightOn() );

			//Show Candle Light
			myCandles->show_light( screen );

			//Show Stats like map & candlemeter
			myFlowers->show_stats( screen, myRidingHood->isLightOn(), myRidingHood->isExtraLightOn() );
			myRidingHood->show_stats( screen, myMap->getX(), myMap->getY(), myFlowers->getOriginalCoords(), myFlowers->Collected() );


			//Render screen
			SDL_Flip( screen );


			//FRAME CAPPING
			if( myTimer->get_ticks() < 1000 / FRAMES_PER_SECOND ){
				SDL_Delay( 1000 / FRAMES_PER_SECOND - myTimer->get_ticks() );
			}

			show_tutorials();

			//Quit if end
			if( myMap->isEnd() ){
				myInstructions->show( screen, TUT_ENDING );
				show_loading( screen );
				quit = true;
				myMenu->notStarted();
				Restart();
			}

			//Quit if die
			if( myRidingHood -> getHP() <= 0 ){

				Mix_PlayChannel( 1, Die, 0 );
				SDL_Delay( 2000 );

				show_loading( screen );
				quit = true;
				myMenu->notStarted();
				Restart();
			}

		}

		if( quit == true ){
			Mix_HaltMusic();
			myRidingHood->NullVel();
		}

		quit = false;

		//Quitting
		if( myMenu->selectedmenu() == 4 ) mainquit = true;


		SDL_Flip( screen );
		if( myTimer->get_ticks() < 1000 / FRAMES_PER_SECOND ){
			SDL_Delay( 1000 / FRAMES_PER_SECOND - myTimer->get_ticks() );
		}

	}

	Mix_HaltMusic();
	Mix_FreeMusic( myMusic );
	Mix_FreeMusic( myMenuMusic );
	Mix_FreeChunk( Die );

	//Deleting Objects
	Delete_Variables();

	Mix_CloseAudio();
	Mix_Quit();
	TTF_Quit();
	SDL_Quit();

	return 0;
}
