#ifndef _RUFUSION_SOJOURNER_H_
#define _RUFUSION_SOJOURNER_H_

// Base types
#include "../Collision/RuCollision_Base.h"
#include "../Scene/Base/RuEntityBase.h"
#include "../Scene/Base/RuEntityModel.h"

#pragma unmanaged

// ************************************************************************************************************************************************************

class CRuFusion_Sojourner : public IRuObject
{
	ruRTTI_DECLARE
	ruHEAP_DECLARE
	ruCLASSGUID_DECLARE

protected:
	enum RuCollisionType
	{
		ruCOLTYPE_NONE			= 0,
		ruCOLTYPE_SURFACE		= 1,
		ruCOLTYPE_EDGE			= 2,
		ruCOLTYPE_POINT			= 3,
		ruCOLTYPE_EMBEDDED		= 4
	};

	struct RuCollider
	{
		INT32						m_triangleIndex;
		CRuPlane4					m_trianglePlane;
		REAL						m_collisionDistance;
		RuCollisionType				m_collisionType;
	};

	IRuObject*						m_collisionObject;

	// Current-run query info
	CRuAAEllipsoid					m_ellipsoid;						//!< The colliding ellipsoid
	CRuVector3						m_velocity;							//!< Ellipsoid velocity
	CRuSphere						m_sphere;

	// Friction settings
	CRuVector3						m_frictionSurfaceNormal;			//!< Normal used for threshold comparison
	REAL							m_frictionSurfaceThreshold;			//!< Threshold at which friction begins to apply
	REAL							m_frictionConstant;					//!< Friction constant

	// Currently enumerated triangles
	CRuSphere						m_lastQueryBounds;					//!< Enumeration bounds
	CRuArrayList<CRuVector3>		m_triangleVerts0;					//!< Enumerated triangle vertices
	CRuArrayList<CRuVector3>		m_triangleNormals0;					//!< Enumerated triangle normals
	CRuArrayList<UINT32>			m_triangleFlags0;					//!< Enumerated triangle surface flags

	// Temporaries
	CRuVector3						m_ellipsoidOrigin;
	CRuMatrix4x4					m_ellipsoidDeformation;
	CRuArrayList<CRuVector3>		m_triangleVerts;
	CRuArrayList<CRuVector3>		m_triangleNormals;
	CRuArrayList<CRuPlane4>			m_trianglePlanes;

	CRuArrayList<RuCollider>		m_colliders;
	CRuArrayList<INT32>				m_skipList;	

	// Statistics
	INT32							m_passed;
	INT32							m_path_Embedded;
	INT32							m_path_Surface;
	INT32							m_path_Point;
	INT32							m_path_Edge;
/*
	// Debugging model
	CRuDynamicMesh*					m_visualizerMesh;
	CRuMaterial*					m_visualizerMaterial;
	CRuModel*						m_visualizerModel;
*/
public:
									CRuFusion_Sojourner(IRuObject *collisionObject);

	void							SetColisionObject(IRuObject *collisionObject);
	void							SetFrictionParameters(const CRuVector3 &frictionSurfaceNormal, REAL frictionSurfaceThreshold, REAL frictionConstant);

	CRuModel*						GetVisualizer();

	BOOL							Slide(const CRuVector3 &origin, const CRuVector3 &velocity, const CRuVector3 &radius, CRuVector3 &adjustedPositionOut);
	BOOL							IntersectsWaterSurface(const CRuSegment3 &segment);

protected:
	CRuVector3						CollideAndStop(const CRuRay3 &collisionRay, const REAL speed);
	CRuVector3						CollideAndSlide(const CRuRay3 &collisionRay, const REAL speed);
	BOOL							IsEmbedded(INT32 triangleIndex, const CRuVector3 &sphereCenter, CRuVector3 &closestPointOut);
	void							ProcessColliders(const CRuRay3 &collisionRay, const REAL speed);
};

// ************************************************************************************************************************************************************

#pragma managed

#endif
