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

#pragma once

#include "glmSDKAPI.h"

#include <glmAbstractTrigger.h>
#include <glmSimuEntityHandle.h>
#include <glmBasePhysicsDefinitions.h>

namespace glm
{
	struct CollisionData;
	class EntityType;

	/**
	 * \class CollisionFilter
	 */
	class GLM_SDK_API CollisionFilter
	{

	public:	//types and structures
		GLM_CLASS_STAT_ID(glm::MemoryStatIds::Simulation)

		struct CollisionSide
		{
			enum Value
			{
				NONE			= 0,
				COLLIDER		= (1<<0),
				COLLIDED		= (1<<1),
				BOTH			= COLLIDER|COLLIDED,
			};
		};

		struct FilterMode
		{
			enum Value
			{
				NONE				= 0,
				PHYSICS_MODE		= (1 << 0),
				ENTITY_TYPE_ID		= (1 << 1),
				RIGID_BODY_ID		= (1 << 2),
				ENTITY_COLLISION_ID = (1 << 3),
				ALL_IDS = ENTITY_TYPE_ID | RIGID_BODY_ID | ENTITY_COLLISION_ID,
				ENTITY_TYPE_COLOR	= (1 << 4),
				BONE_COLOR			= (1 << 5),
				RIGID_BODY_COLOR	= (1 << 6),
				ALL_COLORS			= ENTITY_TYPE_COLOR|BONE_COLOR|RIGID_BODY_COLOR,
				VELOCITY			= (1 << 7),
				MASS				= (1 << 8),
				KINETIC_ENERGY		= (1 << 9)
			};
		};
		
		struct FilterElement
		{
			CollisionSide::Value _filterCollisionSide;
			FilterMode::Value _filterMode;
			int _physicsModeMask;					//used for: PHYSICS_MODE  (needs to be filled with '1 << PhysicsMode::Value', which allows to set several possible values at once)
			ComparisonOperator::Value _operator;	//used for every mode except PHYSICS_MODE
			int _intValue;							//used for: ENTITY_TYPE_ID | RIGID_BODY_ID | ENTITY_COLLISION_ID
			float _floatValue;						//used for: VELOCITY|MASS|KINETIC_ENERGY
			uint32_t _colorABGRValue;				//used for: ENTITY_TYPE_COLOR|BONE_COLOR|RIGID_BODY_COLOR
		};

	public: //static data and methods

		//entry for the entityType KB
		static const char*	_collisionIdKBEntryName;
		static int64_t		_collisionIdKBEntryHashKey;		//this is the hashkey to use on an entityType to get the correct Collision ID

		static bool isCollidingWithCollisionID(PODArray<int>& entityCollisionIds, const CollisionData& currentCollision, CollisionSide::Value collisionSide, ComparisonOperator::Value fitlerComparisonOperator, int filterId);

	public:	//methods
		CollisionFilter();
		virtual ~CollisionFilter();

		/**
		* \brief Return true if at least one of the collisions (collisionData array) pass the filter
		*/
		bool doFilter(EntityType* collidedEntityType, int64_t collidedEntityindex, const glm::Array<CollisionData>& colliderCollisionsData) const;
		void doFilter(glm::Array<int>& outCollisionsIndices, EntityType* collidedEntityType, int64_t collidedEntityindex, const glm::Array<CollisionData>& colliderCollisionsData, bool returnAtFirstCollision=false) const;

	public:	//data
		glm::Array<FilterElement> _filterElements;
		int64_t _entityTypeIdKBHashKey;		//this is the hashkey to use on an entityType to get the correct Crowd entity type ID (as seen by the user, instead of as seen by the SDK)
	} ;
}
