#include <v_lib.h>
#include "phasesp.h"
#include "icond.h"
#include "util.h"
#include "psys.h"
#include "monitor.h"

particle_system_p
parse_psdl_script(char *filename)
{
	CALLER_NAME(parse_psdl_script)
	particle_system_p ps = NULL;
	vhandle_t lex;
	lex = lexParseFile(filename,"[,;]{}");
	if(LIBV_INVALID_HANDLE == lex)
		return NULL;
	lexSetInteger(lex,LEX_COMMENT_CHAR,COMMENT_CHAR);
	lexEnable(lex,LEX_ONE_CHAR_COMMENTS);
	if(!lexSkipToL(lex,"goal"))
		goto err_exit;
	conlPrintf(LOG_INFO,"%s(): found goal for particle system \"%s\".\n", caller_name, lexNext(lex));
	ps = psLoad(lex,lexLast(lex));
	if(!ps)
		goto err_exit;
	LEX_CHECK_NEXT(lex,open_brace);
	while(lexNext(lex))
	{
		if(lexLastWas(lex,"dump_radii"))
		{
			u32_t i;
			vhandle_t out;
			LEX_CHECK_SEMICOLON(lex);
			out = fileOpenWrite("radii.txt");
			for(i = 0;i < ps->num_particles;i++)
				filePrintf(out,"%g\n",ps->particle_radius[i]);
			fileClose(out);
			continue;
		}
		if(lexLastWas(lex,"sp_max_recursions"))
		{
			s32_t spmr;
			if(!lexNextInteger(lex,&spmr))
			{
				SYN_EXPECTED(lex,"int sp_max_recursions");
				goto err_exit;
			}
			if(spmr < 1)
			{
				SYN_EXPECTED(lex,"int sp_max_recursions >= 1");
				goto err_exit;
			}
			LEX_CHECK_SEMICOLON(lex);
			ps->sp_max_recursions = (u32_t)spmr;
			continue;
		}
		if(lexLastWas(lex,"soft_particles"))
		{
			if(!lexNextBoolean(lex,&ps->soft_particles))
			{
				SYN_EXPECTED(lex,"boolean soft_particles");
				goto err_exit;
			}
			LEX_CHECK_SEMICOLON(lex);
			continue;
		}
		if(lexLastWas(lex,"sp_repulsion_factor"))
		{
			if(!lexNextFloat(lex,&ps->sp_repulsion_factor))
			{
				SYN_EXPECTED(lex,"float sp_repulsion_factor");
				goto err_exit;
			}
			LEX_CHECK_SEMICOLON(lex);
			continue;
		}
		if(lexLastWas(lex,"time_limit"))
		{
			if(!lexNextFloat(lex,&ps->solution_time_limit))
			{
				SYN_EXPECTED(lex,"float time_limit");
				goto err_exit;
			}
			LEX_CHECK_SEMICOLON(lex);
			continue;
		}
		if(lexLastWas(lex,"saves_per_second"))
		{
			if(!lexNextInteger(lex,(s32_p)&ps->saves_per_second))
			{
				SYN_EXPECTED(lex,"integer saves_per_second");
				goto err_exit;
			}
			LEX_CHECK_SEMICOLON(lex);
			continue;
		}
		if(lexLastWas(lex,"num_nearest"))
		{
			if(!lexNextInteger(lex,(s32_p)&ps->num_nearest))
			{
				SYN_EXPECTED(lex,"integer num_nearest");
				goto err_exit;
			}
			if(ps->num_nearest < 2)
			{
				SYN_EXPECTED(lex,"integer num_nearest must be greater than 1");
				goto err_exit;
			}
			LEX_CHECK_SEMICOLON(lex);
			continue;
		}
		if(lexLastWas(lex,"nonview_skips"))
		{
			if(!lexNextInteger(lex,(s32_p)&ps->nonview_skips))
			{
				SYN_EXPECTED(lex,"integer nonview_skips");
				goto err_exit;
			}
			LEX_CHECK_SEMICOLON(lex);
			continue;
		}
		if(lexLastWas(lex,"ms_global_scale"))
		{
			if(!lexNextFloat(lex,&ps->ms_global_scale))
			{
				SYN_EXPECTED(lex,"float ms_global_scale");
				goto err_exit;
			}
			LEX_CHECK_SEMICOLON(lex);
			continue;
		}
		if(lexLastWas(lex,"realtime_limit"))
		{
			if(!lexNextFloat(lex,&ps->solution_realtime_limit))
			{
				SYN_EXPECTED(lex,"float realtime_limit");
				goto err_exit;
			}
			LEX_CHECK_SEMICOLON(lex);
			continue;
		}
		if(lexLastWas(lex,"RK_tolerance"))
		{
			if(!lexNextFloat(lex,&ps->solution_RK_tolerance))
			{
				SYN_EXPECTED(lex,"float RK_tolerance");
				goto err_exit;
			}
			LEX_CHECK_SEMICOLON(lex);
			continue;
		}
		if(lexLastWas(lex,"maximal_step"))
		{
			if(!lexNextFloat(lex,&ps->solution_maximal_step))
			{
				SYN_EXPECTED(lex,"float maximal_step");
				goto err_exit;
			}
			LEX_CHECK_SEMICOLON(lex);
			continue;
		}
		if(lexLastWas(lex,"minimal_step"))
		{
			if(!lexNextFloat(lex,&ps->solution_minimal_step))
			{
				SYN_EXPECTED(lex,"float minimal_step");
				goto err_exit;
			}
			LEX_CHECK_SEMICOLON(lex);
			continue;
		}
		if(lexLastWas(lex,"RK_timeout"))
		{
			if(!lexNextFloat(lex,&ps->solution_RK_timeout))
			{
				SYN_EXPECTED(lex,"float RK_timeout");
				goto err_exit;
			}
			LEX_CHECK_SEMICOLON(lex);
			continue;
		}
		if(lexLastWas(lex,"view"))
		{
			if(!lexNext(lex))
			{
				SYN_UNEXPECTED_EOF(lex);
				goto err_exit;
			}
			if(strlen(lexLast(lex)) >= MAX_MONITOR_DATA)
			{
				PARSE_ERROR(lex,"strlen(setup) >= MAX_MONITOR_DATA");
				goto err_exit;
			}
			strCopy(ps->monitor_setup,lexLast(lex),MAX_MONITOR_DATA);
			LEX_CHECK_SEMICOLON(lex);
			continue;
		}
		if(lexLastWas(lex,"save_last_phase"))
		{
			if(!lexNext(lex))
			{
				SYN_UNEXPECTED_EOF(lex);
				goto err_exit;
			}
			strCopy(ps->final_filename, lexLast(lex), _MAX_PATH);
			LEX_CHECK_SEMICOLON(lex);
			continue;
		}
		if(lexLastWas(lex,close_brace))
		{
			lexDestroy(lex);
			return ps;
		}
		PARSE_ERROR(lex,"unknown token");
		goto err_exit;
	}
	SYN_UNEXPECTED_EOF(lex);
err_exit:;
	lexDestroy(lex);
	if(ps)
	{
		ps->final_filename[0] = 0;
		psFree(ps);
	}
	return NULL;

}
