#include <v_lib.h>
#include "draw.h"
#include "psy.h"
#include "ms_wr.h"
#include "monitor.h"
#include "psys.h"
#include "util.h"
#include "phasesp.h"

extern vboolean monitor_extra(particle_system_p ps);

V_LOCAL vboolean V_CALL
ode_monitor(void_p arg,vec_t t,vec_t x[])
{
	vec_t rt;
	vboolean retval;
	particle_system_p ps = (particle_system_p)arg;
	ps->cur_time = t;
	ps->cur_phase = x;
	if(ps->monitor && ps->monitoring_context)
		retval = ps->monitor(ps);
	else
	{
		conlPrintf(LOG_TRACE,"ode_monitor(): time %g\n",t);
		retval = true;
	}
	retval = retval && monitor_extra(ps);
	if(retval)
	{
		rt = timerTime(ps->rt_timer);
		if(t >= ps->solution_time_limit)
		{
			conPrintf("ode_monitor(): time limit (%g) reached "
				"(realtime %g).\n",ps->solution_time_limit,rt);
			retval = false;
		}
		else if(rt >= ps->solution_realtime_limit)
		{
			conPrintf("ode_monitor(): realtime limit (%g) reached "
				"(time %g).\n",ps->solution_realtime_limit,t);
			retval = false;
		}
	}
	if(retval)
		return true;
	ps->end_monitoring(ps);
	ps->end_monitoring = NULL;
	ps->monitor = NULL;
	ps->monitoring_context = NULL;
	ps->ode_monitor = NULL;
	ps->ode_monitor_arg = NULL;
	return false;
}

vboolean
init_monitoring(particle_system_p ps)
{
	vboolean retval;
	if(!ps)
		return false;
	ps->ode_monitor = NULL;
	ps->ode_monitor_arg = NULL;
	ps->monitor = NULL;
	ps->end_monitoring = NULL;
	ps->monitoring_context = NULL;
	if(!ps->nodraw)
		retval = init_draw_context(ps);
	else if(ps->output_maxscript)
		retval = init_ms_context(ps);
	else
		retval = init_psy_context(ps);
	if(retval)
	{
		ps->ode_monitor = ode_monitor;
		ps->ode_monitor_arg = ps;
		return true;
	}
	return false;
}

void
shutdown_monitoring(particle_system_p ps)
{
	if(!ps)
		return;
	if(ps->end_monitoring)
		ps->end_monitoring(ps);
	ps->ode_monitor = NULL;
	ps->ode_monitor_arg = NULL;
	ps->monitor = NULL;
	ps->end_monitoring = NULL;
	ps->monitoring_context = NULL;
}
