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

#define	memAllocVecs(n) \
	((vec_p)memAllocZ((n) * sizeof(vec_t)))
	
particle_system_p
alloc_particle_system(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_reciprocal_mass = memAllocVecs(num_particles);
	ps->particle_6_pi_eta_r = memAllocVecs(num_particles);
	ps->phase = (vec_p)memAllocZ(PHASESPACE_BYTES(num_particles));
	ps->force = (vec3_t*)memAllocZ(num_particles * sizeof(vec3_t));
	ps->saves_per_second = 10;
	ps->solution_RK_tolerance = 1e-2;
	ps->solution_RK_timeout = 10;
	ps->solution_maximal_step = MAXFLOAT;
	ps->rt_timer = timerCreate();
	ps->contact = matAlloc(num_particles, num_particles);
	ps->dist = matAlloc(num_particles, num_particles);
	ps->dglue = 1e-6;
	ps->hglue = 0;
	ps->deltaz = 0;
	strCopy(ps->file_name,"[null]",_MAX_PATH);
	return ps;
}

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

void
free_particle_system(particle_system_p ps)
{
	if(!ps)
		return;
	if(ps->final_filename[0])
	{
		char path[_MAX_PATH], dir[_MAX_PATH], name[_MAX_PATH], ext[_MAX_PATH] = {0};
		fsSplitPath(ps->final_filename,dir,name,ext);
		if(!ext[0])
		{
			/* save in both formats */
			fsMakePath(path,dir,name,"ms");
			psy_save_pos(ps, path, true);
			fsMakePath(path,dir,name,"csv");
			psy_save_pos(ps, path, false);
		}
		else
		{
			psy_save_pos(ps, ps->final_filename, strcasecmp(ext, "ms") ? false : true);
		}
	}
	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_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->force)
		memFree(ps->force);
	if(ps->contact)
		memFree(ps->contact);
	if(ps->dist)
		memFree(ps->dist);
	memFree(ps);
}
