
//---------------------------------------------------------------------
// 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/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;
static int  flag_colvo = 0;
static int  flag_wanna = 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;

		//  debug
		if (strcmp(argv[i], "-inf") == 0 
				|| strcmp(argv[i], "-i") == 0) 
			flag_colvo = 1;
	};
};


//=== FLAGS ===


class CGame {
public : 
	CError *Error;

	CHabitat Habitat;	
	CRobot *Robot;
	CData *Data;
	CSocket *Socket;
	CExecuter *Exe;
	CLexic *Lexic;
	CSyntax *Syntax;
	CRun *Run;

public :
	CGame() 
	{ 
		Data = Habitat.GetDataAddr();
		Socket = Habitat.GetSocketAddr();
		Robot = new CRobot(Data, Socket); 
		Exe = new CExecuter(Data, Robot);
		Exe -> SetDebugMode(flag_debug);
		Run = new CRun(Exe);
		Error = new CError();
	};

	~CGame() 
	{ 
		delete Robot; 
		delete Exe;
		delete Run;
		delete Error;
		if (Lexic!=NULL) delete Lexic;
		if (Syntax!=NULL) delete Syntax;
	};

	void  Compile(char* s);
	void  PlayBot(char* argv[], bool q);
	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(), Run);
	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");

		Run->Execute();

		printf("\n");
		Habitat.WaitingTurn();
	} while ( Robot->IsWin() == 0 );
	//=========================
	Habitat.Destroy();
};


//--- CGame :: PlayBot
void CGame :: PlayBot(char* argv[], bool q) 
{
	printf("\n\n\n --- Playbot ---");
	printf("\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;
	CData  DNull;
	Game.Compile(argv[1]);
	int wins = 0; 
	int loos = 0; 

	if (Game.Syntax->GetPassed())
	do {
		(*Game.Data) = DNull;
		Game.PlayBot(argv, !flag_colvo);

		if (Game.Data->win > 0)
			wins += Game.Data->win;
		else 
			loos += Game.Data->win;

		printf("\n\n~Info: winner is %d times. looser is %d times.\n", wins, loos);
		sleep(1);
		
	} while (flag_colvo);

	return 0;
}


