#include "IPhysicsWorld.h"

using namespace std; // Visual Studio 2005

IPhysicsWorld::IPhysicsWorld()
{
	m_world = NewtonCreate(physicsAlloc, physicsFree);
}

IPhysicsWorld::~IPhysicsWorld()
{

}

void IPhysicsWorld::setSolverModel(ENUMERATED_SOLVER_MODEL solverModel)
{
	NewtonSetSolverModel(m_world, solverModel);
}

void IPhysicsWorld::setPlatformArchitecture(ENUMERATED_PLATFORM_ARCHITECTURE platformArchitecture)
{
	NewtonSetPlatformArchitecture(m_world, platformArchitecture);
}

void IPhysicsWorld::setFrictionModel(ENUMERATED_FRICTION_MODEL frictionModel)
{
	NewtonSetFrictionModel(m_world, frictionModel);
}

void IPhysicsWorld::manualUpdate(f32 timeStep)
{
	NewtonUpdate(m_world, timeStep);
}

void IPhysicsWorld::setMinimumFrameRate(f32 frameRate)
{
	NewtonSetMinimumFrameRate(m_world, frameRate);
}

f32 IPhysicsWorld::getTimeStep()
{
	return NewtonGetTimeStep(m_world);
}

/// Sets the Newton world size.
//! IPhysics starts the Newton world at a default size of -1000 units to +1000 units in all directions. If you find that your
//! physics entities freeze unexpectedly, or fall and fall and then freeze, it's quite likely that they have passed the edge
//! of the Newton world boundary, in which case use this to enlarge it.
void IPhysicsWorld::setWorldSize(vector3df minEdge, vector3df maxEdge)
{
	f32 min[3];
	min[0] = minEdge.X * IrrToNewton;
	min[1] = minEdge.Y * IrrToNewton;
	min[2] = minEdge.Z * IrrToNewton;
	f32 max[3];
	max[0] = maxEdge.X * IrrToNewton;
	max[1] = maxEdge.Y * IrrToNewton;
	max[2] = maxEdge.Z * IrrToNewton;

	NewtonSetWorldSize(m_world, &min[0], &max[0]);
}

void IPhysicsWorld::setEntityLeaveWorldEvent(NewtonBodyLeaveWorld callback)
{
	NewtonSetBodyLeaveWorldEvent(m_world, callback);
}

void IPhysicsWorld::forEachBodyDo(NewtonBodyIterator callback)
{
	NewtonWorldForEachBodyDo(m_world, callback);
}

void IPhysicsWorld::forEachBodyInBoxDo(aabbox3d<f32> box, NewtonBodyIterator callback)
{
	NewtonWorldForEachBodyInAABBDo(m_world, &box.MinEdge.X, &box.MaxEdge.X, callback);
}

f32 IPhysicsWorld::getVersion()
{
	return NewtonWorldGetVersion (m_world);
}

void IPhysicsWorld::freezeEntity(IPhysicsBaseEntity* entity)
{
	NewtonWorldFreezeBody(m_world, entity->getBody());
}

void IPhysicsWorld::unfreezeEntity(IPhysicsBaseEntity* entity)
{
	NewtonWorldUnfreezeBody(m_world, entity->getBody());
}

/// Get a pointer to the Newton world.
//! This is provided in case you need to make some direct calls to Newton.
NewtonWorld* IPhysicsWorld::getWorld()
{
	return m_world;
}

void* IPhysicsWorld::physicsAlloc(int size)
{
    return new char[size];
}

void IPhysicsWorld::physicsFree(void *pointer, int size)
{
	char *tmp;
	tmp = (char*) pointer;

//TODO
//	delete[] tmp;
}

void IPhysicsWorld::close()
{
//	cout << "3.2" << endl;
	NewtonDestroyAllBodies(m_world);
	NewtonMaterialDestroyAllGroupID(m_world);
	NewtonDestroy(m_world);
}
