/*
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 *
 * cmo - (C)ontact (MO)deler.
 *
 * (C) Vladimir A. Smirnov (kkatarn@sleepgate.ru, smirnov@nocnt.ru), 2011.
 *
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 *
 * This program parses control file (see 'test.fcic') and creates
 * box(es) with randomly distributed fibers, then computes number of
 * contacts between them and extrapolates volumetric content to the value
 * corresponting the equality between numbers of fibers and contacts.
 *
 * The 'toy' version of this program - with visualisation stuff - is in
 * antiglut source tarball. This version is much more complicated, but
 * includes no visualisation stuff. Just the computation, nothing more.
 *
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 */

#include <v_lib.h>
#include "rgcache.h"
#include "genparse.h"
#include "seqparse.h"
#include "sysproto.h"

vhandle_t lex;
vp_stack_t gens = TYPED_STACK_EMPTY_INITIALIZER;
vp_stack_t seqs = TYPED_STACK_EMPTY_INITIALIZER;
vp_stack_t syss = TYPED_STACK_EMPTY_INITIALIZER;

/*
#define	FLAG_AUTONAME	0
#define	FLAG_VERBOSE	1

struct cmdflag_s
{
	char short_name;
	char *long_name;
	vboolean found;
}	cmdflags[] = 
{
	{'a', "--autoname", false},
	{'v', "--verbose", false},
	{0, NULL, false}
};

static vboolean
set_flags(int argc, char *argv[])
{
	for(i = 1;i < argc;i++)
	{
		if(argv[i][0] != '-')
			continue;
		if(argv[i][1] == '--')
			set_long_flag(argv[i]);
		else
			set_short_flags(argv[i]);
	}
}
*/

int main(int argc, char *argv[])
{
	CALLER_NAME(main)
	vboolean verbose = false;
	int i;
	char *script = "test.fcic";
	FILE *out = stdout;
	logStartConsoleLog();
	logUpperLevel(LOG_TRACE);
/*	set_flags(argc, argv); */
	for(i = 1;i < argc;i++)
	{
		if(!strcmp(argv[i], "--verbose"))
			verbose = true;
		else if(!strcmp(argv[i], "--autoname"))
		{
			if(out != stdout)
			{
				fclose(out);
				puts("--autoname is meaningless with --outfile.");
				return -1;
			}
			out = NULL;
		}
		else if(!strcmp(argv[i], "--outfile"))
		{
			if(out == NULL)
			{
				puts("--outfile is meaningless with --autoname.");
				return -1;
			}
			if(++i >= argc)
				return -1;
			if(strcmp(argv[i],"-"))
			{
				out = fopen(argv[i],"wb");
				if(!out)
				{
					perror("fopen");
					return -1;
				}
			}
		}
		else
			script = argv[i];
	}

	lex = lexParseFile(script, "{}()[];");
	if(!lex)
		return -1;

	lexSetInteger(lex, LEX_COMMENT_CHAR, '#');
	lexEnable(lex, LEX_ONE_CHAR_COMMENTS);
	lexSetInteger(lex, LEX_FP_DOMAIN, LEX_FP_DOMAIN_POSITIVE);
	lexEnable(lex, LEX_FP_DOMAIN_CHECK);

	while(lexNext(lex))
	{
		if(lexLastWas(lex, "generators")) {
			if(parseGenerators(lex, &gens) > 0)
				continue;
		} else if(lexLastWas(lex, "sequence")) {
			if(parseSequence(lex, &gens, &seqs))
				continue;
		}
		SYN_EXPECTED(lex,"generators|sequence");
		break;
	}
	if(!lexLast(lex))
	{
		if(verbose)
		{
			genPrint(&gens);
			seqPrint(&seqs);
		}
		if(sysCreateSystems(&seqs, &syss))
		{
			if(verbose)
				sysPrint(&syss);
			if(sysSequentialScheduler(&syss))
			{
				if(verbose)
					sysPrint(&syss);
				sysPostprocess(&syss, out);
			}
			else
			{
				ERROR_GENERIC("error during computation");
			}
		}
		else
		{
			ERROR_GENERIC("error creating systems");
		}
	}
	if(out && out != stdout)
		fclose(out);
    sysDestroy(&syss);
    genDestroy(&gens);
    seqDestroy(&seqs);
	lexDestroy(lex);
	if(verbose)
		memPrintStats();
	return 0;
}
