#include "BulletManager.h"
#include "InputManager.h"

BulletManager* BulletManager::m_pInstance = 0;

BulletManager *BulletManager::getInstance() 
{
	if (m_pInstance == 0) 
	{
		m_pInstance = new BulletManager();
	}
	return m_pInstance;
}

BulletManager::BulletManager()
{
	btDefaultCollisionConfiguration* collisionConfiguration = new btDefaultCollisionConfiguration();
	btCollisionDispatcher* dispatcher = new	btCollisionDispatcher(collisionConfiguration);
	btBroadphaseInterface* overlappingPairCache = new btDbvtBroadphase();
	btSequentialImpulseConstraintSolver* solver = new btSequentialImpulseConstraintSolver;
	m_dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,overlappingPairCache,solver,collisionConfiguration);
	m_dynamicsWorld->setGravity(btVector3(0,-10,0));
	m_playerBody = 0;
}

void BulletManager::tick(int nFps)
{
}

void BulletManager::addPhysicsShape(PhysicsShape *shape)
{
	btCollisionShape* bodyShape = shape->getCollisionShape();
	if (bodyShape == 0) 
	{
		return;
	}
	btTransform bodyTransform;
	bodyTransform.setIdentity();
	bodyTransform.setFromOpenGLMatrix(&shape->getMatrix()[0][0]);
	btScalar mass(0.);
	btVector3 localInertia(0,0,0);
	btDefaultMotionState* myMotionState = new btDefaultMotionState(bodyTransform);
	btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,bodyShape,localInertia);
	btRigidBody *body = new btRigidBody(rbInfo);
	m_dynamicsWorld->addRigidBody(body);
}

void BulletManager::clearDynamicsWorld()
{
	delete m_dynamicsWorld;
	btDefaultCollisionConfiguration* collisionConfiguration = new btDefaultCollisionConfiguration();
	btCollisionDispatcher* dispatcher = new	btCollisionDispatcher(collisionConfiguration);
	btBroadphaseInterface* overlappingPairCache = new btDbvtBroadphase();
	btSequentialImpulseConstraintSolver* solver = new btSequentialImpulseConstraintSolver;
	m_dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,overlappingPairCache,solver,collisionConfiguration);
	m_playerBody = 0;
}

void BulletManager::createPlayerBody(Camera *camera)
{
	btCollisionShape* bodyShape = new btCapsuleShape(.3f,2.0f);
	btTransform bodyTransform;
	bodyTransform.setIdentity();
	float *translate = camera->getEye();
	bodyTransform.setOrigin(btVector3(translate[0],translate[1]-0.79f,translate[2]));
	btScalar mass(10.);
	btVector3 localInertia(0,0,0);
	bodyShape->calculateLocalInertia(mass,localInertia);
	btDefaultMotionState* myMotionState = new btDefaultMotionState(bodyTransform);
	btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,bodyShape,localInertia);
	m_playerBody = new btRigidBody(rbInfo);
	m_playerBody->setAngularFactor(0);
	m_dynamicsWorld->addRigidBody(m_playerBody);
}

bool BulletManager::playerBodyExists() 
{ 
	return m_playerBody!=0;
}

void BulletManager::updateDynamicsWorld(float nSpeed, Camera *camera)
{
	// move camera
	float nOldEye[3];
	nOldEye[0] = camera->getEyeX();
	nOldEye[1] = camera->getEyeY();
	nOldEye[2] = camera->getEyeZ();
	if (InputManager::getInstance()->isKeyDown('w') || InputManager::getInstance()->isKeyDown('W'))
	{
		camera->moveForward(nSpeed*0.1f);
	}
	if (InputManager::getInstance()->isKeyDown('s') || InputManager::getInstance()->isKeyDown('S'))
	{
		camera->moveBackward(nSpeed*0.1f);
	}
	if (InputManager::getInstance()->isKeyDown('a') || InputManager::getInstance()->isKeyDown('A'))
	{
		camera->moveLeft(nSpeed*0.1f);
	}
	if (InputManager::getInstance()->isKeyDown('d') || InputManager::getInstance()->isKeyDown('D'))
	{
		camera->moveRight(nSpeed*0.1f);
	}
	float *nNewEye = camera->getEye();
	m_playerBody->activate(true);
	m_playerBody->setLinearVelocity(100.0f*btVector3(nNewEye[0]-nOldEye[0],-0.04f,nNewEye[2]-nOldEye[2]));

	// check physics
	m_dynamicsWorld->stepSimulation(1.f/60.f,10);

	// update camera
	btVector3 camPos = m_playerBody->getWorldTransform().getOrigin();
	camera->setPosition(camPos[0],camPos[1]+0.8,camPos[2]);
}