#include "psmod.h"

vboolean
phaseSave(char *dest,char *scriptfile,vec_t time,vec_t *phase,
	u32_t num_vec3_fields,u32_t num_elements,char *field_names[])
{
	CALLER_NAME(phaseSave)
	u32_t fld, i;
	vec_t *ptr;
	vhandle_t out;
	if(!dest || !phase || !num_vec3_fields || !num_elements || !field_names)
	{
		ERROR_GENERIC(error_incorrect_parameters);
		return false;
	}
	out = fileOpenSafeOverwrite(dest);
	if(!out)
		return false;
	filePrintf(out,"phase\n"
		"source \"%s\"\n"
		"time %g\n"
		"num_vec3_fields %u\n"
		"num_elements %u\n",scriptfile ? scriptfile : "NUL",
		time,num_vec3_fields,num_elements);
	for(fld = 0;fld < num_vec3_fields;fld++)
	{
		ptr = phase + fld * 3;
		filePrintf(out,"\"%s\"\n",field_names[fld]);
		for(i=0;i < num_elements;i++)
		{
			filePrintf(out,"%g\t%g\t%g\n",ptr[0],ptr[1],ptr[2]);
			ptr += 3 * num_vec3_fields;
		}
	}
	fileClose(out);
	return true;
}

vboolean phaseLoad(char *src,char *scriptfile,vec_t *time_ret,
	vec_t *phase_ret,u32_t num_vec3_fields,u32_t num_elements,
	char *field_names[])
{
	CALLER_NAME(phaseLoad)
	s32_t iv;
	u32_t fld, i;
	vec_t *ptr, v[3];
	vhandle_t in;
	if(!src || !phase_ret || !num_vec3_fields || !num_elements || !field_names)
	{
		ERROR_GENERIC("incorrect parameter(s)");
		return false;
	}
	in = lexParseFile(src,"");
	if(!in)
		return false;
	if(!lexNextIs(in,"phase"))
	{
		SYN_EXPECTED(in,"phase");
		lexDestroy(in);
		return false;
	}
	if(!lexNextIs(in,"source"))
	{
		SYN_EXPECTED(in,"source");
		lexDestroy(in);
		return false;
	}
	if(!lexNextIs(in,"NUL"))
	{
		if(!scriptfile || !lexLastWas(in,scriptfile))
		{
			WARNING_GENERIC("different source of phase");
		}
	}
	if(!lexNextIs(in,"time"))
	{
		SYN_EXPECTED(in,"time");
		lexDestroy(in);
		return false;
	}
	if(!lexNextFloat(in,v))
	{
		SYN_EXPECTED(in,"float <production_time>");
		lexDestroy(in);
		return false;
	}
	if(time_ret)
		*time_ret = v[0];
	if(!lexNextIs(in,"num_vec3_fields"))
	{
		SYN_EXPECTED(in,"num_vec3_fields");
		lexDestroy(in);
		return false;
	}
	if(!lexNextInteger(in,&iv))
	{
		SYN_EXPECTED(in,"integer <num_vec3_fields>");
		lexDestroy(in);
		return false;
	}
	if(iv < (s32_t)num_vec3_fields)
	{
		ERROR_GENERIC("got 'num_vec3_fields' that is lesser than expected");
		lexDestroy(in);
		return false;
	}
	if(!lexNextIs(in,"num_elements"))
	{
		SYN_EXPECTED(in,"num_elements");
		lexDestroy(in);
		return false;
	}
	if(!lexNextInteger(in,&iv))
	{
		SYN_EXPECTED(in,"integer <num_elements>");
		lexDestroy(in);
		return false;
	}
	if(iv < (s32_t)num_elements)
	{
		ERROR_GENERIC("got 'num_elements' that is lesser than expected");
		lexDestroy(in);
		return false;
	}
	else if(iv > (s32_t)num_elements)
	{
		WARNING_GENERIC("got 'num_elements' that is greater than expected");
	}
	/*
	 * All checks passed. Load components of the the phase.
	 */
	lexPush(in,LEX_POSITION_BIT);
	for(fld = 0;fld < num_vec3_fields;fld++)
	{
		ptr = phase_ret + fld * 3;
		/*
		 * Search for component #fld
		 */
		lexPop(in,LEX_POSITION_BIT);
		lexPush(in,LEX_POSITION_BIT);
		if(!lexSkipTo(in,field_names[fld]))
		{
			lexPop(in,LEX_POSITION_BIT);
			ERROR_INVALID_STR("unknown phase component",field_names[fld]);
			lexDestroy(in);
			return false;
		}
		for(i=0;i < num_elements;i++)
		{
			if(!lexNextFloat(in,v) || !lexNextFloat(in,v+1) || 
				!lexNextFloat(in,v+2))
			{
				SYN_EXPECTED(in,"three floats");
				lexPop(in,LEX_POSITION_BIT);
				lexDestroy(in);
				return false;
			}
			vec3Copy(ptr,v);
			ptr += 3 * num_vec3_fields;
		}
	}
	lexPop(in,LEX_POSITION_BIT);
	lexDestroy(in);
	return true;
}
