/***************************************************************************
*                                                                          *
*  Copyright (C) Golaem S.A.  All Rights Reserved.                         *
*                                                                          *
****************************************************************************/

#pragma once

#include "glmPhysX.h" //needed for inheritance to physx::PxErrorCallback
#include <glmApex.h>
#include <glmLog.h>
#include "glmSDKAPI.h"
#include "glmMemory.h"

#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4275)
#endif

namespace glm
{
	class PhysicsWorld_PhysX;
	class GlmApexRenderResourceManager;

	/**
	* \brief PhysX statics
	*/
	extern GLM_SDK_API bool hasPhysXPhysics();
	extern GLM_SDK_API physx::PxPhysics& getPhysXPhysics();
	extern GLM_SDK_API physx::PxCooking& getPhysXCooking();
	extern GLM_SDK_API physx::PxConvexMesh* getPhysXCylinder();
	extern GLM_SDK_API physx::PxPvd* getPhysXPvd();

	extern void GLM_SDK_API initPhysXSimulation(const PhysicsWorld_PhysX* physicsWorld, bool usePVD, float approximateObjectSize);
	extern void GLM_SDK_API finishPhysXSimulation(const PhysicsWorld_PhysX* physicsWorld);

	extern GLM_SDK_API physx::PxCudaContextManager* initCudaContextManager(const PhysicsWorld_PhysX* physicsWorld);
	extern GLM_SDK_API void finishCudaContextManager(const PhysicsWorld_PhysX* physicsWorld);

	/**
	* \brief Apex statics
	*/
	extern GLM_SDK_API nvidia::apex::ApexSDK& getApexSDK();
	extern GLM_SDK_API nvidia::apex::ModuleClothing& getApexClothing();
	extern GLM_SDK_API nvidia::apex::UserRenderResourceManager& getApexRenderResourceManager();

	extern void GLM_SDK_API initApexSimulation(const PhysicsWorld_PhysX* physicsWorld);
	extern void GLM_SDK_API finishApexSimulation(const PhysicsWorld_PhysX* physicsWorld);

	/**
	* \brief Init
	*/
	void allocatePhysX();
	void deallocatePhysX();

	/**
	* \brief Golaem error logger for PhysX
	*/
	class GLM_SDK_API PhysXErrorCallback : public physx::PxErrorCallback
	{
	public:
		GLM_CLASS_STAT_ID(glm::MemoryStatIds::Simulation)

		void reportError(physx::PxErrorCode::Enum code, const char* message, const char* file, int line)
		{
			switch (code)
			{
			case physx::PxErrorCode::eDEBUG_INFO:
				GLM_SDK_TRACE_INFO("DEBUG_INFO in PhysX/Apex module (file: " << file << " line: " << line << "): " << message);
				break;
			case physx::PxErrorCode::eDEBUG_WARNING:
				GLM_SDK_TRACE_WARNING("DEBUG_WARNING in PhysX/Apex module (file: " << file << " line: " << line << "): " << message);
				break;
			case physx::PxErrorCode::ePERF_WARNING:
				GLM_SDK_TRACE_WARNING_LIMIT("PERF_WARNING in PhysX/Apex module (file: " << file << " line: " << line << "): " << message);
				break;
			default:
				GLM_SDK_TRACE_WARNING("Error " << code << " in PhysX/Apex module (file: " << file << " line: " << line << "): " << message);
			}
		}
	};
}

#ifdef _MSC_VER
#pragma warning(pop)
#endif
