#ifndef PSYS_H
#define PSYS_H

#include "ctrl.h"

#define MAX_BOUNDARY_PLANES     16
#define MAX_BOUNDARY_SPHERES    16
#define MAX_MONITOR_DATA        1024

typedef struct particle_system_s
{
	int     random_seed;
	u32_t   num_particles;
	vec_t   *particle_radius;
	vec_t   *particle_density;
	vec_t   *particle_mass;
	vec_t   *particle_reciprocal_mass; /* 1/m_j */
	vec_t   *particle_6_pi_eta_r; /* 6 * M_PI * env_eta * r_j */

	u32_t   num_boundary_planes;
	u32_t   num_boundary_spheres;
	
	vec4_t  boundary_plane[MAX_BOUNDARY_PLANES];
	float_controller_t plane_interaction[MAX_BOUNDARY_PLANES];
	vec_t   plane_interaction_arg[MAX_BOUNDARY_PLANES][MAX_CTRL_ARGS];

	vec4_t  boundary_sphere[MAX_BOUNDARY_SPHERES];
	float_controller_t sphere_interaction[MAX_BOUNDARY_PLANES];
	vec_t   sphere_interaction_arg[MAX_BOUNDARY_PLANES][MAX_CTRL_ARGS];

	float_controller_t binary_interaction;
	vec_t   binary_interaction_arg[MAX_CTRL_ARGS];

	vec_t   env_eta;
	vec3_controller_t env_velocity;
	vec_t   env_velocity_arg[MAX_CTRL_ARGS];

	vec3_controller_t unary_force;
	vec_t   unary_force_arg[MAX_CTRL_ARGS];

	vec3_controller_t unary_accel;
	vec_t   unary_accel_arg[MAX_CTRL_ARGS];

	vec_t   solution_time_limit;
	vec_t   solution_realtime_limit;
	vec_t   solution_RK_tolerance;
	vec_t   solution_RK_timeout;
	vboolean nodraw;
	vboolean output_maxscript;

	vec_t   *phase; /* positions & velocities of all particles */
	vec_t   cur_time;   /* as processed by ODE solver */
	vhandle_t rt_timer; /* used to measure elapsed time */
	vec_t   *cur_phase; /* as processed by ODE solver */
	u32_t   cur_idx; /* used by controller calls */
	vec_t   common[MAX_CTRL_ARGS]; /* used by controller calls */
	vec3_t  *force; /* used by right-side routine */
	vhandle_t ode_solver;
	u32_t   saves_per_second;
	char    monitor_setup[MAX_MONITOR_DATA];
	vboolean (V_CALL *monitor)(struct particle_system_s *ps);
	vboolean (V_CALL *end_monitoring)(struct particle_system_s *ps);
	void_p  monitoring_context;
	vboolean (V_CALL *ode_monitor)(void_p arg,vec_t time,vec_t phase[]);
	void_p  ode_monitor_arg;
	u32_t   step_rejection_count;

}   particle_system_t, *particle_system_p;

particle_system_p
alloc_particle_system(u32_t num_particles);

void
free_particle_system(particle_system_p ps);

#endif  /* !PSYS_H */
