#include <time.h>
#include "../common/vector.h"
#include "../common/misc.h"
#include "simulation.h"
#include "../common/debug.h"
#include "solvers.h"

extern scene_data *main_scene;
extern int running;
extern state *current_state;
extern double gravity;
extern int current_sim;
extern int sim_type;

double spring_mass = 5;
double spring_rest = 0;
double spring_constant = 15;
double spring_damp = 0.5;


void calc_spring_force(vector *force, state *old_state)
{
	multiply_vector(force, force, 0);
	force->y = -old_state->position.y * spring_constant;
	force->y += spring_damp * old_state->velocity.y * old_state->position.y;
}

void calc_spring_acceleration(state *new_state, state *old_state)
{
	vector force;
	
	calc_spring_force(&force, old_state);
	
	//acceleration
	multiply_vector(&new_state->velocity, &force, 1/spring_mass);
	new_state->velocity.y += gravity;
}


void run_spring()
{
	vector old_position;

	copy_vector(&current_state->position, &old_position);
	
	if(current_sim == RK4 && running)
		run_rk4((void* (*)(state*, state*))&calc_spring_acceleration, current_state);
	else if(current_sim == MIDPOINT && running)
		run_midpoint((void* (*)(state*, state*))&calc_spring_acceleration, current_state);
	else if(current_sim == EULER && running)
		run_euler((void* (*)(state*, state*))&calc_spring_acceleration, current_state);

	//graphical junk
	copy_vector(&current_state->position, &MASS_OBJ->pos);
	MASS_OBJ->pos.y += 0.5;
	
	copy_vector(&current_state->position, &SPRING_OBJ->pos);
	
	if(distance_between(&current_state->position, &old_position) > EPSILON)
	{
		capture_state(current_state);
	}
}


void reset_spring_state()
{
	multiply_vector(&current_state->position, &current_state->position, 0);
	multiply_vector(&current_state->velocity, &current_state->position, 0);
	running = 0;
}


void release_spring()
{
	//clear old values
	reset_spring_state();
	running = 1;
}
