#include "example1.h"

using namespace std;

#define PEG_ROWS 10
#define PEG_COLS 10

#define RAIN_ROWS 8
#define RAIN_COLS 40

RatPhysicsExample1::RatPhysicsExample1(string name): RatPhysicsExample(name), viewheight(0) {}
RatPhysicsExample1::RatPhysicsExample1(const char *name): RatPhysicsExample(name), viewheight(0) {}
RatPhysicsExample1::RatPhysicsExample1(char *name): RatPhysicsExample(name), viewheight(0) {}

static void rain_left_world(rat_world *thisworld,rat_body *thisbody,void *userdata)
{
	RatPhysicsExample1 *phys=(RatPhysicsExample1 *)userdata;

	vector2 newpos={phys->bounds.x/2.0,-75};
	rat_hull_set_pos(thisbody->hull,newpos);
	vector2_set(&(thisbody->velocity),0,0);
}

static rat_body *make_peg(rat_real x,rat_real y)
{
	vector2 pos={x,y};
	vector2 verts[3]=
	{
		{0,-24},
		{-13,0},
		{13,0}
	};
	return rat_body_create(
		rat_hull_polygon_create(pos,3,verts),
		0.7,1.0,0.0,0.0);
}
static rat_body *make_ball(rat_real x,rat_real y)
{
	vector2 center={x,y};
	return rat_body_create(
		rat_hull_circle_create(center,9.6),
		0.7,1.0,rat_area_circle(9.6),
		rat_moi_circle(rat_area_circle(9.6),9.6));
}

static bool is_even(int i)
{
	return (rat_real)i/2.0f==(rat_real)(i/2);
}

bool RatPhysicsExample1::InitWorld()
{
	SDL_WM_SetCaption(title.c_str(),NULL);

	aabb space={{0,-100},{bounds.x,bounds.y+100}};
	vector2 cell_size={150,150};
	vector2 gravity={0,6};

	world=rat_world_create(space,rat_integrator_euler,10,
		rat_body_manager_type_quad_tree,&cell_size);

	rat_world_set_gravity(world,gravity);

	for (register unsigned int i=0; i<RAIN_ROWS*RAIN_COLS; i++)
	{
		rat_body *ball=make_ball(
			(i%RAIN_COLS)*(bounds.x/(rat_real)RAIN_COLS),
			(i/RAIN_COLS)*(150.0/(rat_real)RAIN_ROWS)-100);
		rat_world_add_body(world,ball);
	}

	for (register unsigned int i=0; i<PEG_ROWS*PEG_COLS; i++)
	{
		bool isthiseven=is_even(i/PEG_COLS);
		rat_real colstart=(bounds.x/(rat_real)PEG_COLS)*0.5;
		rat_real stagger=isthiseven?colstart:0;
		rat_body *peg=make_peg(
			(i%PEG_COLS)*(bounds.x/(rat_real)PEG_COLS)+stagger+colstart/2.0,
			(i/PEG_COLS)*(bounds.y/(rat_real)PEG_ROWS)+100);
		rat_world_add_body(world,peg);
	}

	rat_world_set_body_left_world_callback(world,rain_left_world,this);

	return (bool)world;
}

bool RatPhysicsExample1::UpdateWorld(rat_real timestep)
{
	timestep=timestep>2.0?2.0:timestep;
	rat_world_update(world,timestep*0.05,timestep<=1.0?1:0);

	if (timestep)
	{
		if (keys[SDLK_UP]) viewheight+=timestep*2.0;
		if (keys[SDLK_DOWN]) viewheight-=timestep*2.0;
	}
	else
	{
		if (keys[SDLK_UP]) viewheight+=2.0;
		if (keys[SDLK_DOWN]) viewheight-=2.0;
	}

	viewheight=viewheight<-100?-100:viewheight;
	viewheight=viewheight>100?100:viewheight;
	pickoffset.y=-viewheight;

	return true;
}

bool RatPhysicsExample1::UpdateVisuals()
{
	glMatrixMode(GL_MODELVIEW);
	glPushMatrix();
		glTranslatef(0,viewheight,0);
		rat_draw_world(world,show_quadtree,show_arbiters,show_aabbs);
	glPopMatrix();
	return true;
}

bool RatPhysicsExample1::FreeWorld()
{
	rat_world_free_entities(world);
	rat_world_destroy(world);

	return true;
}
