/*
Final Frontier Trader
by TomT64

Requires the following libraries:
SDL >= 1.2.4
SDL_image >= 1.2.2
SDL_mixer >= 1.2.4
SDL_ttf >= 2.0.6
SDL_gfx >= 2.0.8
physfs (with zip support) >= 0.1.9
Python 2.4.x

SDL and its libraries may be found easily through Google
or SDL's website (http://www.libsdl.org).
PhysFS may be found at its website (http://www.icculus.org/physfs/)
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string>
#include <time.h>
#include <math.h>

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

#include "engine.h"
#include "fftfile.h"
#include "input.h"
#include "graphics.h"
#include "gui.h"
#include "guiapply.h"
#include "map.h"
#include "scenario.h"
#include "shop.h"
#include "units.h"

int SCREEN_WIDTH;
int SCREEN_HEIGHT;
TTF_Font *font;
TTF_Font *font2;

FFTInput *fftinput;
Preferences *prefs;
StarField *stars;
StarField *stars2;
Scenario *mainScen;
Unit *ship;
Engine *engine;
Map *map;
Mix_Chunk *shot;
Mix_Chunk *explode;

int SMOOTH=1;
std::string VERSION="0.70 alpha";

static bool LoadScenario();

#define PI 3.1415926535897932384626433832795

int main ( int argc, char *argv[] )
{
	bool fullscreen=false;
	bool software=false;
	bool showfps=false;
	if (argc>1)
	{
		int i;
		for (i=1; i<argc; i++)
		{
			if (!strcmp(argv[i],"-nosmooth"))
			{
				SMOOTH=0;
			}
			if (!strcmp(argv[i],"-fullscreen"))
			{
				fullscreen=true;
			}
			if (!strcmp(argv[i],"-software"))
			{
				software=true;
			}
			if (!strcmp(argv[i],"-showfps"))
			{
				showfps=true;
			}
			if (!strcmp(argv[i],"-log"))
			{
				Log::Init("fft.log");
			}
			if (!strcmp(argv[i],"-verbose"))
			{
				Log::EnableVerbose();
			}
		}
	}
	Log::Write("Final Frontier Trader\nversion %s\nby TomT64\n------------\n",VERSION.c_str());
	// We initalize the random number generator
	srand(time(NULL));
	engine=new Engine();
	if (showfps) engine->ShowFPS();

	SDL_Surface *screen=SDL_GetVideoSurface();
	fftinput=new FFTInput;
	int init=PHYSFS_init(argv[0]); //init physfs
	if (!init)
	{
		Log::WriteVerbose("Failed to initialize PHYSFS.  Reason: %s",PHYSFS_getLastError());
		exit(1);
	}
	Log::WriteVerbose("PHYSFS initialized successfully");
	char **i;
	for (i = PHYSFS_getSearchPath(); *i != NULL; i++)
	Log::WriteVerbose("[%s] is in the search path.at the beginning of execution", *i);

	PHYSFS_addToSearchPath(PHYSFS_getBaseDir(), 0); //fpk dir
	PHYSFS_setWriteDir(PHYSFS_getBaseDir());
	Log::WriteVerbose("Loading Preferences");
	prefs=new Preferences("prefs");
	delete fftinput;
	fftinput=prefs->GetInput();
	engine->SetInput(fftinput);
	PHYSFS_addToSearchPath("fpk/base.fpk", 1); //load base packfile
	SCREEN_WIDTH = 640;
	SCREEN_HEIGHT = 480;

	if(TTF_Init()==-1) {
	Log::WriteVerbose("TTF_Init: %s", TTF_GetError());
	exit(2);
	}
	Log::WriteVerbose("SDL_ttf initialized successfully");

	// load font
	font=LoadTTF("fonts/arial.ttf", 10);
	if(!font) {
	Log::WriteVerbose("Unable to Open font 'fonts/arial.ttf' -  TTF_OpenFont: %s", TTF_GetError());
	// handle error
	}
	engine->AddFont("font10",font);
	font2=LoadTTF("fonts/arial.ttf", 14);
	if(!font2) {
	Log::WriteVerbose("Unable to Open font 'fonts/arial.ttf' - TTF_OpenFont: %s", TTF_GetError());
	// handle error
	}
	engine->AddFont("font14",font2);
	Log::WriteVerbose("Main Fonts loaded");

	/* initialize SDL */
	#ifdef DEBUG
	if( SDL_Init(SDL_INIT_VIDEO|SDL_INIT_AUDIO|SDL_INIT_NOPARACHUTE) < 0 ) {
		Log::WriteVerbose("Could not initialize SDL: %s",SDL_GetError());
		return -1;
	}
	#else
	if( SDL_Init(SDL_INIT_VIDEO|SDL_INIT_AUDIO) < 0 ) {
		Log::WriteVerbose("Could not initialize SDL: %s",SDL_GetError());
		return -1;
	}
	#endif

	Log::WriteVerbose("SDL initialized successfully");

	//atexit(SDL_Quit);

	/* set the title bar */
	SDL_WM_SetCaption("Final Frontier Trader", "Final Frontier Trader");
	SDL_Surface *icon = LoadICON("gfx/ico/fftico.png");
	engine->AddSurface("main icon",icon);
	SDL_WM_SetIcon(icon, NULL);
	Log::WriteVerbose("Icon and caption in place");

	/* create window */
	screen = SDL_SetVideoMode(400, 300, 0, SDL_HWSURFACE|SDL_DOUBLEBUF);
	//CenterWindow();
	Log::WriteVerbose("Video mode set and centered");

	SDL_Surface *bg = LoadIMG("gfx/startupbg.png");
	engine->AddSurface("splash screen",bg);
	DrawIMG(bg,0,0);
	SDL_Flip(screen);
	Log::WriteVerbose("Splash screen displayed");

	stars = new StarField;
	stars2 = new StarField;
	stars->Init(SCREEN_WIDTH, SCREEN_HEIGHT);
	stars2->Init(SCREEN_WIDTH, SCREEN_HEIGHT);
	engine->AddStarfield(stars, false, 10);
	engine->AddStarfield(stars2, true, 20);
	Log::WriteVerbose("Beginning warp stars initialized");

	char **k;
	std::string fpktemp=" ";
	char **fpklist=PHYSFS_enumerateFiles("fpk");
	for (k = fpklist; *k != NULL; k++)
	{
		if (strcmp(fpktemp.c_str(),"base.fpk") && IsFPK(*k))
		{
			fpktemp="fpk/";
			fpktemp+=*k;
			PHYSFS_addToSearchPath(fpktemp.c_str(), 1);
		}
	}
	PHYSFS_freeList(fpklist);
	Log::WriteVerbose("All FPKs placed in search path");

	ship = new Unit;
	ship->Init(0, 0, "gfx/ship/ship.png","base.fpk",(float)0.01);
	engine->SetMainShip(ship);
	Log::WriteVerbose("Main ship initialized");

	map = new Map;
	map->Init(1);
	engine->SetMap(map);
	Log::WriteVerbose("Map initialized");

	if(Mix_OpenAudio(22050, AUDIO_S16SYS, 2, 2048) < 0)
	{
		Log::WriteVerbose("Warning: Couldn't set 22050 Hz 16-bit audio\n- Reason: %s", SDL_GetError());
	}
	shot = LoadSound("sound/shoot.wav");
	explode = LoadSound("sound/expl01.wav");
	engine->AddSound("shot", shot);
	engine->AddSound("explode", explode);
	Log::WriteVerbose("Audio initialized and sounds loaded");

	SDL_Delay(1000);

	//reset res
	if (fullscreen && software)
	{
		if (SDL_VideoModeOK(SCREEN_WIDTH, SCREEN_HEIGHT, 32, SDL_SWSURFACE|SDL_FULLSCREEN))
		{
			screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, 32, SDL_SWSURFACE|SDL_FULLSCREEN);
		}
		else engine->Quit();
	}
	else if (fullscreen)
	{
		if (SDL_VideoModeOK(SCREEN_WIDTH, SCREEN_HEIGHT, 32, SDL_HWSURFACE|SDL_DOUBLEBUF|SDL_FULLSCREEN))
		{
			screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, 32, SDL_HWSURFACE|SDL_DOUBLEBUF|SDL_FULLSCREEN);
		}
		else engine->Quit();
	}
	else if (software) screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, 0, SDL_SWSURFACE);
	else screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, 0, SDL_HWSURFACE|SDL_DOUBLEBUF);
	CenterWindow();
	Log::WriteVerbosen("Main window set to 640x480 ");
	if (fullscreen) Log::WriteVerbosen("at fullscreen ");
	else Log::WriteVerbosen("at windowed ");
	if (software) Log::WriteVerbosen("software mode");
	else Log::WriteVerbosen("hardware mode");
	Log::WriteVerbose(" and centered");

	int done=0;
	int maintemp=0;
	int GUIresult;
	Log::WriteVerbose("Proceeding to main loop");
	while(!done)
	{
		GUIresult=RunStartingGUI(SCREEN_WIDTH, SCREEN_HEIGHT);
		Log::WriteVerbose("Option from Starting GUI selected");
		if (GUIresult==-1)
		{
			done=1;
			Log::WriteVerbose("Exiting game");
		}
		if (GUIresult==2)
		{
			bool goahead=false;
			Log::WriteVerbose("Entering New Game");
			goahead=LoadScenario();
			if (goahead)
			{
				Log::WriteVerbose("Proceeding to main game play");
				bool init=engine->StartGame();
				if (init) maintemp=engine->MainLoop();
				engine->CleanUpGame();
				Log::WriteVerbose("Main gameplay exited");
				if (maintemp==-1) done=1;
			}
		}
	}

	/* clean up */
	engine->Quit();

	return 0;
}

static bool LoadScenario()
{
	//float zoom=0.5;
	int done;
	done=0;
	while (!done)
	{
		//bool goahead=false;
		Log::WriteVerbose("LoadScenario()");
		Log::WriteVerbose("Entering Scenario selection");
		std::string scenselect=ChooseScenario();
		if (!strcmp(scenselect.c_str(),"")) return false;
		Log::WriteVerbose("Scenario Selection is %s",scenselect.c_str());
		delete mainScen;
		mainScen = new Scenario();
		Log::WriteVerbose("Reading Scenario information");
		engine->SetMainModule(scenselect);
		done=1;
		//mainScen->ReadOnly(scenselect);
		//goahead=ShipSelect(zoom, scenselect);
		//if (goahead) done=1;
	}
	return true;
}

