/*
 * Instituto Superior de Engenharia do Porto
 *
 * Estruturas de Informação
 *
 * 2000/2001
 *
 * (C) Paulo Sousa
 *
 * ------------------------------------------
 *
 * Trabalho nº 1
 *
 */


#include "teste.h"



#include <cstring>
using namespace std;


//
// variavel global contendo as opcoes de configuracao
//
configuracao_t g_configuracao;

void init_configuracao()
{
	g_configuracao.bOutput2File = false;
	g_configuracao.bUseLimits = true;
	g_configuracao.sFileName = "";
	g_configuracao.bUseSlow = false;
	g_configuracao.bUseMiliseg = false;
}

bool encontra(char* vec[], int nSize, const char* szParam, int& valor)
{
	// skip vArgs[0]
	for (int i = 1; i < nSize; i++)
	{
		if (strstr(vec[i], szParam) == vec[i])
		{
			char* pstr = vec[i]+strlen(szParam);
			sscanf(pstr, "%d", &valor);
			return true;
		}
	}
	return false;
}

string parse_filename(int nArgs, char* vArgs[])
{
	// skip vArgs[0]
	for (int i = 1; i < nArgs; i++)
	{
		if (strstr(vArgs[i], "f=") == vArgs[i])
		{
			char* pstr = vArgs[i]+strlen("f=");
			string s(pstr);
			return s;
		}
	}
	return "";
}

bool parse_limites(int nArgs, char* vArgs[])
{
	int iB = 1;
	if (encontra(vArgs, nArgs, "l=", iB))
	{
		if (iB == 0)
			return false;
		else
			return true;
	}
	else
		return true;
}

bool parse_lentos(int nArgs, char* vArgs[])
{
	int iB = 1;
	if (encontra(vArgs, nArgs, "e=", iB))
	{
		if (iB == 0)
			return false;
		else
			return true;
	}
	else
		return false;
}

bool parse_miliseg(int nArgs, char* vArgs[])
{
	int iB = 1;
	if (encontra(vArgs, nArgs, "u=", iB))
	{
		if (iB == 0)
			return false;
		else
			return true;
	}
	else
		return false;
}

int parse_modo(int nArgs, char* vArgs[])
{
	int modo = -1;
	encontra(vArgs, nArgs, "m=", modo);
	return modo;
}

int parse_runs(int nArgs, char* vArgs[])
{
	int runs = 1;
	encontra(vArgs, nArgs, "r=", runs);
	return runs;
}

int parse_ignore(int nArgs, char* vArgs[])
{
	int ignore = 0;
	encontra(vArgs, nArgs, "ir=", ignore);
	return ignore;
}

int parse_tamanho(int nArgs, char* vArgs[])
{
	int tamanho = 1000;
	encontra(vArgs, nArgs, "t=", tamanho);
	return tamanho;
}

int parse_tamInf(int nArgs, char* vArgs[])
{
	int tamInf = 1000;
	encontra(vArgs, nArgs, "ti=", tamInf);
	return tamInf;
}

int parse_tamSup(int nArgs, char* vArgs[])
{
	int tamSup = 10000;
	encontra(vArgs, nArgs, "ts=", tamSup);
	return tamSup;
}

int parse_inc(int nArgs, char* vArgs[])
{
	int inc = 1000;
	encontra(vArgs, nArgs, "i=", inc);
	return inc;
}

algoritmo parse_algoritmo(int nArgs, char* vArgs[])
{
	int sp = qsort5;
	encontra(vArgs, nArgs, "sp=", sp);
	return (algoritmo)sp;
}

preenchimento parse_preenchimento(int nArgs, char* vArgs[])
{
	int fp = aleatorio;
	encontra(vArgs, nArgs, "fp=", fp);
	return (preenchimento)fp;
}


int do_command_line(int nArgs, char* vArgs[])
{
	/*
	for (int i = 0; i < nArgs; i++)
		cout << "[" << i << "] " << vArgs[i] << endl;
	*/

	/***

	 Sintaxe da linha de comandos

		trabalho1 l=?UsaLimites e=?UsaLentos f=?NomeFicheiro u=?UsaMilisegundos

		trabalho1 m=1 t=?Tamanho r=?Runs ir=?Ignore

		trabalho1 m=2 fp=?Preenchimento ti=?TamInf ts=?TamSup i=?Incremento r=?Runs ir=?Ignore

		trabalho1 m=3 sp=?Algoritmo ti=?TamInf ts=?TamSup i=?Incremento r=?Runs ir=?Ignore

		trabalho1 m=4 sp=?Algoritmo fp=?Preenchimento t=?Tamanho r=?Runs ir=?Ignore

	 ***/

	g_configuracao.sFileName = parse_filename(nArgs, vArgs);
	if (g_configuracao.sFileName != "")
		g_configuracao.bOutput2File = true;
	else
		g_configuracao.bOutput2File = false;
	g_configuracao.bUseLimits = parse_limites(nArgs, vArgs);
	g_configuracao.bUseSlow = parse_lentos(nArgs, vArgs);
	g_configuracao.bUseMiliseg = parse_miliseg(nArgs, vArgs);

	int modo = parse_modo(nArgs, vArgs);
	if (modo == -1)
		//assume que apenas modificou as configurações
		return 1;

	int runs = parse_runs(nArgs, vArgs);
	int ignore = parse_ignore(nArgs, vArgs);

	switch (modo)
	{
	case 1:
		{
		int tamanho = parse_tamanho(nArgs, vArgs);
		algoritmo* vec_sp;
		int nAlgs = gera_vec_sp(vec_sp);

		view_teste_modo_1(vec_sp, nAlgs, tamanho, runs, ignore);
		delete [] vec_sp;
		return 0;
		}
		break;
	case 2:
		{
		preenchimento fp = parse_preenchimento(nArgs, vArgs);
		int tamInf = parse_tamInf(nArgs, vArgs);
		int tamSup = parse_tamSup(nArgs, vArgs);
		int inc = parse_inc(nArgs, vArgs);
		algoritmo* vec_sp;
		int nAlgs = gera_vec_sp(vec_sp);

		view_teste_modo_2(vec_sp, nAlgs, fp, tamInf, tamSup, inc, runs, ignore);
		delete [] vec_sp;
		return 0;
		}
		break;
	case 3:
		{
		algoritmo sp = parse_algoritmo(nArgs, vArgs);
		int tamInf = parse_tamInf(nArgs, vArgs);
		int tamSup = parse_tamSup(nArgs, vArgs);
		int inc = parse_inc(nArgs, vArgs);

		view_teste_modo_3(sp, tamInf, tamSup, inc, runs, ignore);
		return 0;
		}
		break;
	case 4:
		{
		algoritmo sp = parse_algoritmo(nArgs, vArgs);
		preenchimento fp = parse_preenchimento(nArgs, vArgs);
		int tamanho = parse_tamanho(nArgs, vArgs);

		view_teste_modo_4(sp, fp, tamanho, runs, ignore);
		return 0;
		}
		break;
	default:
		cout << "parametros invalidos" << endl;
		return -1;
		break;
	}

	return 0;
}

void menu_conf()
{
	char op;
	do {
		cout << endl;
		cout << endl;
		cout << "***  C O N F I G U R A C A O  ***" << endl;
		cout << "   1 - Usa Limites (actual= " << tostring(g_configuracao.bUseLimits) << ")" << endl;
		cout << "   2 - Usa Lentos (actual= " << tostring(g_configuracao.bUseSlow) << ")"  << endl;
		cout << "   3 - Usa Milisegundos (actual= " << tostring(g_configuracao.bUseMiliseg) << ")"  << endl;
		cout << "   0 - sair" << endl << endl;

		cout << ":> ";
		cin >> op;
		switch (op)
		{
		case '1':
			g_configuracao.bUseLimits = !g_configuracao.bUseLimits;
			break;
		case '2':
			g_configuracao.bUseSlow = !g_configuracao.bUseSlow;
			break;
		case '3':
			g_configuracao.bUseMiliseg = !g_configuracao.bUseMiliseg;
			break;
		}
	} while (op != '0');
}

int main(int nArgs, char* vArgs[])
{

	/****

	cout << 0 << " " << 0.1 << " " << 1 << " " << 1.4 << endl;
	cout << setiosflags(ios::showpoint) << 0 << " " << 0.1 << " " << 1 << " " << 1.4 << endl;
	cout << setiosflags(ios::scientific) << 0 << " " << 0.1 << " " << 1 << " " << 1.4 << endl;
	cout << setiosflags(ios::fixed) << 0 << " " << 0.1 << " " << 1 << " " << 1.4 << endl;
	return 1;
     
	 ****/


	init_configuracao();

	if (nArgs > 1)
	{
		int r = do_command_line(nArgs, vArgs);
		//verificar se só mudou configurações
		if (r != 1)
			return r;
	}

	char op;
	do {
		cout << endl;
		cout << endl;
		cout << "***  M E N U  ***" << endl;
		cout << "   1 - modo 1 (dimensao fixa; preenchimento variavel; algoritmo variavel)" << endl;
		cout << "   a - modo 1a (dimensao fixa; preenchimento variavel; varios algoritmos)" << endl;
		cout << "   2 - modo 2 (dimensao variavel; preenchimento fixa; algoritmo variavel)" << endl;
		cout << "   b - modo 2a (dimensao variavel; preenchimento fixa; varios algoritmos)" << endl;
		cout << "   3 - modo 3 (dimensao variavel; preenchimento variavel; algoritmo fixo)" << endl;
		cout << "   4 - teste a um algoritmo" << endl;
		cout << "   9 - configuracao" << endl;
		cout << "   0 - sair" << endl << endl;

		cout << ":> ";
		cin >> op;
		switch (op)
		{
		case '1':
			modo_1(true);
			break;
		case 'a':
		case 'A':
			modo_1(false);
			break;
		case '2':
			modo_2(true);
			break;
		case 'b':
		case 'B':
			modo_2(false);
			break;
		case '3':
			modo_3();
			break;
		case '4':
			modo_4();
			break;
		case '9':
			menu_conf();
			break;
		}
	} while (op != '0');

	return 0;
}




