
//---------------------------------------------------------------------
// Includes
#include "stdio.h"

#include "ui/onerror.hpp"

#include "mod/lang/lex.hpp"
#include "mod/lang/syn.hpp"
#include "mod/lang/exec.hpp"
#include "mod/lang/sem.hpp"

#include "mod/robot/habitat.hpp"
#include "mod/robot/robot.hpp"
#include "mod/robot/data.hpp"


//--- Defines 
#define DEF_NAME "tka4bot"
#define DEF_HOST "127.0.0.1"


//--- FLAGS ---
static bool flag_printlex = false;
static int  flag_botname = -1;
static int  flag_host = -1;
static int  flag_wait = -1;
static int  flag_debug = -1;

//--- Get flags from argv
void GetFlags(int argc, char* argv[]) 
{
	for (int i = 1; i<argc; i++) {
		//  print lexems
		if (strcmp(argv[i], "-printlex") == 0 
				|| strcmp(argv[i], "-pl") == 0) 
			flag_printlex = true;
		//  name
		if (strcmp(argv[i], "-name") == 0 
				|| strcmp(argv[i], "-n") == 0) 
			flag_botname = i+1;
		//  host
		if (strcmp(argv[i], "-host") == 0 
				|| strcmp(argv[i], "-h") == 0) 
			flag_host = i+1;
		//  host
		if (strcmp(argv[i], "-wait") == 0 
				|| strcmp(argv[i], "-w") == 0) 
			flag_wait = i+1;
		//  debug
		if (strcmp(argv[i], "-debug") == 0 
				|| strcmp(argv[i], "-d") == 0) 
			flag_debug = 1;
	};
};


//=== FLAGS ===


class CGame {
public : 
	CError *Error;

	CHabitat Habitat;	
	CRobot *Robot;
	CData *Data;
	CSocket *Socket;
	CExecuter *Exe;
	CLexic *Lexic;
	CSyntax *Syntax;

public :
	CGame() 
	{ 
		Data = Habitat.GetDataAddr();
		Socket = Habitat.GetSocketAddr();
		Robot = new CRobot(Data, Socket); 
		Exe = new CExecuter(Data, Robot);
		Exe->SetDebugMode(flag_debug);
		Error = new CError();
	};

	~CGame() 
	{ 
		delete Robot; 
		delete Exe;
		delete Error;
		if (Lexic!=NULL) delete Lexic;
		if (Syntax!=NULL) delete Syntax;
	};

	void  Compile(char* s);
	void  PlayBot(char* argv[]);
	void  GoBot(char *host, int portno, char* gamer_name, int to_wait);
};


//---------------------------------------------------------------------

//--- CGame :: Compile
void CGame :: Compile(char* s)
{
	Lexic = new CLexic(s);
	if (!Lexic->MakeAnalysis()) Error->OnError("Lexical analysis did not pass.", -510);
	if (flag_printlex) Lexic->Print();
	printf("\n~Info: Lexical analysis was passed.\n");

	Syntax = new CSyntax(Lexic->GetBegin(), Exe);
	if (Syntax->MakeAnalysis()) printf("\n~Info: Syntax analysis was passed.\n");
};


//--- CGame :: Go Bot !
void CGame :: GoBot(char *host, int portno, char* gamer_name, int to_wait) 
{
	Habitat.Init(host, portno, gamer_name, to_wait);
	//------------------------- 
	do  {
			Habitat.Analyze();
			printf("\n");
			Robot->Pass();
			//Game.Exe->Execute();
			printf("\n");
			Habitat.WaitingTurn();
	} while ( Robot->IsWin() == 0 );
	//=========================
	Habitat.Destroy();
};


//--- CGame :: PlayBot
void CGame :: PlayBot(char* argv[]) 
{
	printf("\n\n\n");
	printf("~Quest: Wanna execute your robot? [y/n] \n");
	if ( getchar() != 'y') return;
	printf("\n\n\n");

	int portno = 4774;
	int to_wait = 1;

	//--- Some prepares
	char *host;
	if (flag_host > 0)  host = argv[flag_host];
	else host = strdup(DEF_HOST);
	
	char *gamer_name;
	if (flag_botname > 0)  gamer_name = argv[flag_botname];
	else gamer_name = strdup(DEF_NAME);
	if ( strlen(gamer_name) > STRING_SIZE ) 
		Error->OnError(ERROR_MAIN_LONG_GAMER_NAME);
	
	if (flag_wait > 0)  to_wait = atoi(argv[flag_wait]);
	if (to_wait < 1) Error->OnError(ERROR_MAIN_WAIT_NUMBER);
	//=== Some prepares
	
	GoBot(host,portno,gamer_name,to_wait);
};


//--- MAIN ---
int main(int argc, char* argv[])
{		
	if (argc<2) CError(ERROR_MAIN_WITHOUT_PARAMETERS);
	GetFlags(argc, argv); 
	
	CGame  Game;
	
	Game.Compile(argv[1]);
	//Game.PlayBot(argv);
	Game.Exe->Execute();

	return Game.Error->get_number();
}


