#include <v_lib.h>
#include "config.h"
#include "phasesp.h"
#include "ctrl.h"
#include "psys.h"

extern char outdir[];
extern vboolean psy_save_pos(particle_system_p ps, char *filename, vboolean msform);

#define	memAllocVecs(n) ((vec_p)memAllocZ((n) * sizeof(vec_t)))

V_LOCAL particle_system_p
psAlloc(u32_t num_particles)
{
	particle_system_p ps = NULL;
	ps = memAllocZ(sizeof(particle_system_t));
	ps->num_particles = num_particles;
	ps->particle_radius = memAllocVecs(num_particles);
	ps->particle_density = memAllocVecs(num_particles);
	ps->particle_mass = memAllocVecs(num_particles);
	ps->particle_mass_delta = memAllocVecs(num_particles);
	ps->particle_reciprocal_mass = memAllocVecs(num_particles);
	ps->particle_6_pi_eta_r = memAllocVecs(num_particles);
	ps->dist = matAlloc(num_particles, num_particles);
	ps->surf_dist = matAlloc(num_particles, num_particles);
	ps->phase = memAllocVecs(num_particles * PHASESPACE_DIM);
	ps->force = (vec3_t*)memAllocZ(num_particles * sizeof(vec3_t));
	ps->tangent_forces = false;
	ps->dglue = memAllocVecs(num_particles);
	ps->hglue = 0;
	ps->contact = matAlloc(num_particles, num_particles);
	ps->saves_per_second = 10;
	ps->solution_RK_tolerance = 1e-2;
	ps->solution_RK_timeout = 10;
	ps->solution_maximal_step = MAXFLOAT;
	ps->binary_interaction_max_dist = MAXFLOAT;
	ps->rt_timer = timerCreate();
	ps->deltaz = 0;
	strCopy(ps->file_name,"[null]",_MAX_PATH);
	return ps;
}

void
psFree(particle_system_p ps)
{
	void_p ptr;
	if(!ps)
		return;
	if(ps->final_filename[0])
	{
		char buf1[_MAX_PATH];
		char buf2[_MAX_PATH];
		sprintf(buf1,"%s/final_state/%s.ms",outdir,ps->final_filename);
		sprintf(buf2,"%s/final_state/%s.csv",outdir,ps->final_filename);
		psy_save_pos(ps, buf1, true);
		psy_save_pos(ps, buf2, false);
	}
	if(ps->rt_timer != LIBV_INVALID_HANDLE)
		timerDestroy(ps->rt_timer);
	if(ps->particle_radius)
		memFree(ps->particle_radius);
	if(ps->particle_density)
		memFree(ps->particle_density);
	if(ps->particle_mass)
		memFree(ps->particle_mass);
	if(ps->particle_mass_delta)
		memFree(ps->particle_mass_delta);
	if(ps->particle_reciprocal_mass)
		memFree(ps->particle_reciprocal_mass);
	if(ps->particle_6_pi_eta_r)
		memFree(ps->particle_6_pi_eta_r);
	if(ps->phase)
		memFree(ps->phase);
	if(ps->dglue)
		memFree(ps->dglue);
	if(ps->force)
		memFree(ps->force);
	if(ps->contact)
		memFree(ps->contact);
	if(ps->dist)
		memFree(ps->dist);
	if(ps->surf_dist)
		memFree(ps->surf_dist);
	while(vpsPop(&ps->float_controllers,&ptr))
		memFree(ptr);
	while(vpsPop(&ps->vec3_controllers,&ptr))
		memFree(ptr);
	memFree(ps);
}

STATIC_STRING(key_numparticles, "numparticles");
STATIC_STRING(random_seed, "random_seed");
STATIC_STRING(key_uniform, "uniform");
STATIC_STRING(key_radius, "radius");
STATIC_STRING(key_shells, "shells");
STATIC_STRING(key_tangent_forces, "tangent_forces");
STATIC_STRING(key_particle_density, "particle_density");
STATIC_STRING(key_pairwise, "pairwise");
STATIC_STRING(key_distribution, "distribution");
STATIC_STRING(key_boundary, "boundary");
STATIC_STRING(key_gravity, "gravity");

	amount 400;
	random_seed 5;
	radius uniform 0.7e-2 1.3e-2;
	shells {
		tangent_forces true dglue 5e-3 hglue 0.1;
	}
	particle_density uniform 2700 2700;
	pairwise binary1;
	distribution box1;
	boundary openbox1;
	gravity usual_gravity;
	

particle_system_p psLoad(vhandle_t lex)
{
	CALLER_NAME(psLoad);
	char id[MAX_ID];
	s32_t np;
	particle_system_p ps;
	if(!lexCopyNextToken(lex,id,MAX_ID))
	{
		SYN_EXPECTED(lex,"string particle_system_name")
		return NULL;
	}
	if(!lexNextIs(lex,OPEN_BRACE))
	{
		SYN_EXPECTED(lex,OPEN_BRACE)
		return NULL;
	}
	if(!lexNextIs(lex,key_numparticles))
	{
		SYN_EXPECTED(lex,key_numparticles)
		return NULL;
	}
	if(!lexNextInteger(lex,&np))
}
