#ifndef _COLLISION_MANAGER_H_
#define _COLLISION_MANAGER_H_

#include "Geo_Obj_Physics.h"
#include "Octree.h"
#include <list>

class CollisionManager
{
	// Singleton
	static CollisionManager* sInstance;
	CollisionManager() {};
	CollisionManager(const CollisionManager& im) {}

	std::list<Geo::GeoObjPhysics*> mPhysicsObjects;

	inline void CheckSleep(Geo::GeoObjPhysics& aObjToCheck, Geo::GeoObjPhysics& aOther);
	inline void CheckWake(Geo::GeoObjPhysics& aObjToCheck, Geo::GeoObjPhysics& aOther);
	inline void CheckReflect(Geo::GeoObjPhysics& aObjToCheck, Geo::GeoObjPhysics& aOther, glm::vec3 aCollisionNorm);
	inline void SAT(Geo::GeoObjPhysics& a, Geo::GeoObjPhysics& b, float& aOutPenetration, glm::vec3& aOutNormal);
	inline bool CollidersIntersect(Collider& a, Collider& b);
	void CheckCollision(Geo::GeoObjPhysics& a, Geo::GeoObjPhysics& b);
	void HandleCollision(Geo::GeoObjPhysics& a, Geo::GeoObjPhysics& b);
	void ApplyGravity(Geo::GeoObjPhysics& aObj);

public:
	static CollisionManager& I();
	void CheckForCollisionsAll();
	void ApplyGravityAll();
	void AddPhysicsObject(Geo::GeoObjPhysics& aObj); // TODO Should probably have a good way to remove these objects from list also
	void RewindEnd(); // Called when rewind ends


	// Octree stuff
	#ifdef USE_OCTREE
	private:
		Octree mOctree;
	public:
		void ObjectMoved(Geo::GeoObjPhysics& aObj, glm::vec3 aOldPos) { mOctree.MoveCollider(&aObj.mCollider, aOldPos); }
		void DrawOctree() { mOctree.Draw(); } // For debugging 
	#endif
};

#endif // Close _COLLISION_MANAGER_H_