#pragma once

#include <BulletCollision/CollisionDispatch/btGhostObject.h>
#include <btBulletDynamicsCommon.h>
#include <glm/glm.hpp>

#include "../physics.h"

namespace kek {

struct PhysicsData {
	btDynamicsWorld *world;
};

struct PhysicsObjectData {
	btRigidBody *body;
};

struct PlayerPhysicsObjectData: public PhysicsObjectData {
	btGhostObject *jumpCollider;
};

struct ClosestNotSelfConvexResultCallback: public btCollisionWorld::ConvexResultCallback {
	ClosestNotSelfConvexResultCallback(const btVector3 &convexFromWorld, const btVector3 &convexToWorld, btCollisionObject *self)
		: m_self(self),
		  m_convexFromWorld(convexFromWorld),
		  m_convexToWorld(convexToWorld),
		  m_hitCollisionObject(0) {}

	btCollisionObject *m_self;
	btVector3 m_convexFromWorld; // used to calculate hitPointWorld from hitFraction
	btVector3 m_convexToWorld;

	btVector3 m_hitNormalWorld;
	btVector3 m_hitPointWorld;
	const btCollisionObject *m_hitCollisionObject;

	virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult &convexResult, bool normalInWorldSpace) {
		if(convexResult.m_hitCollisionObject == m_self) return 1.0f;
		m_closestHitFraction = convexResult.m_hitFraction;
		m_hitCollisionObject = convexResult.m_hitCollisionObject;
		if(normalInWorldSpace) {
			m_hitNormalWorld = convexResult.m_hitNormalLocal;
		} else {
			/// need to transform normal into worldspace
			m_hitNormalWorld = m_hitCollisionObject->getWorldTransform().getBasis() * convexResult.m_hitNormalLocal;
		}
		m_hitPointWorld = convexResult.m_hitPointLocal;
		return convexResult.m_hitFraction;
	}
};

namespace Physics {

glm::vec3 toGLM(btVector3 vec);
btVector3 fromGLM(glm::vec3 vec);

glm::quat toGLM(btQuaternion quat);
btQuaternion fromGLM(glm::quat quat);

}

}
