#ifndef PSYS_H
#define PSYS_H

#include "config.h"
#include "ctrl.h"

#define MAX_BOUNDARY_PLANES	 256
#define MAX_BOUNDARY_SPHERES	256
#define MAX_MONITOR_DATA		1024

typedef struct particle_system_s
{
	int	 random_seed;
	char	file_name[_MAX_PATH];
	u32_t   num_particles;
#ifdef		PS_PARALLEL
	/*
	 * Pairs of indices: upper-right triangle.
	 * Length is (num_particles^2 - num_particles) / 2.
	 */
	int		*ij;
	/*
	 * Number of slices (2, 4, 8, e.t.c.) - depends of number of processing units.
	 */
	int		num_slices;
	int		**ij_start; /* num_slices + 1 */
	vhandle_t job_ready;
	vhandle_t *threads;	/* num_slices */
#endif		/* PS_PARALLEL */
	int		fail_counter;
	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 */
	matrix_p dist;
	matrix_p contact;
	vec_t	dglue;
	vec_t	hglue;
	vec_t	deltaz;

	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_maximal_step;
	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 */
	vec3_t  *force; /* used by right-side routine */
	vhandle_t ode_solver;
	u32_t   saves_per_second;
	u32_t   ms_draw_skips;
	vec_t	ms_global_scale;
	u32_t   global_skips;
	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 */
