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

#pragma once

#include "glmSDKAPI.h"
#include "glmPathDefinitions.h"

//golaem core includes
#include <glmAABBTree.h>

namespace glm
{
	class NavigationMesh3;
	/**
	* \brief An AABBTree classifying the cells of any navigation mesh.
	*
	* \ingroup NavigationMeshQueries
	*
	* \author Golaem <dev@golaem.com> 
	*/
	class GLM_SDK_API NavigationMeshCellsAABBTree
	{
	public:

		GLM_CLASS_STAT_ID( glm::MemoryStatIds::Simulation)

		/**
		* \brief Constructor.
		*/
		NavigationMeshCellsAABBTree(const NavigationMesh3 & navigationMesh);

		/**
		* \brief Destructor.
		*/
		~NavigationMeshCellsAABBTree();

		void update();

		/**
		* \brief Retrieve the navigation on top of which this kdtree is built.
		*/
		const NavigationMesh3& getNavigationMesh() const;

		/**
		* \brief Retrieve the AABBtree.
		*/
		const AABBTree & getAABBTree() const;

		/**
		* \brief Retrieve the identifier of the cell which triangle3 has the given address.
		*/
		NavigationMeshCellId getCellId(const Triangle3* cellTriangle3Ptr) const;

		/**
		* \name RayCasts
		*/
		//@{
		/**
		* \brief Check that a sent ray has an intersection with the navigation mesh.
		* \param[in] ray The ray.
		* \param[in] maximumRayLength The length up to which intersections are detected.
		* \return True if an intersection is detected.
		*/
		bool sendRay(const ClassifiedRay3 & ray, float maximumRayLength) const;
		/**
		* \brief Check that a sent ray has an intersection with the navigation mesh.
		* \param[in] ray The ray.
		* \param[in] maximumRayLength The length up to which intersections are detected.
		* \param[out] cellId The identifier of the cell that is intersected, -1 if none are.
		* \return True if an intersection is detected.
		*/
		bool sendRay(const ClassifiedRay3 & ray, float maximumRayLength, NavigationMeshCellId & cellId) const;
		/**
		* \brief Check that a sent ray has an intersection with the navigation mesh.
		* \param[in] ray The ray.
		* \param[in] maximumRayLength The length up to which intersections are detected.
		* \param[out] cellId The identifier of the cell that is intersected, -1 if none are.
		* \param[out] intersectionDistance The distance to the intersection along the ray, -1 if no intersection is detected.
		* \return True if an intersection is detected.
		*/
		bool sendRay(const ClassifiedRay3 & ray, float maximumRayLength, NavigationMeshCellId & cellId, float& intersectionDistance) const;
		/**
		* \brief Check that a sent ray has an intersection with the navigation mesh.
		* \param[in] ray The ray.
		* \param[in] maximumRayLength The length up to which intersections are detected.
		* \param[out] cellId The identifier of the cell that is intersected, -1 if none are.
		* \param[out] intersectionDistance The distance to the intersection along the ray, -1 if no intersection is detected.
		* \param[out] intersectionPoint The intersection point between the cell and the ray.
		* \return True if an intersection is detected.
		*/
		bool sendRay(const ClassifiedRay3 & ray, float maximumRayLength, NavigationMeshCellId & cellId, float & intersectionDistance, Vector3 & intersectionPoint) const;
		//@}

	private:
		/**
		* \brief Forbidden copy constructor.
		*/
		NavigationMeshCellsAABBTree(const NavigationMeshCellsAABBTree&);

		/**
		* \brief Forbidden assignment operator.
		*/
		NavigationMeshCellsAABBTree & operator=(const NavigationMeshCellsAABBTree&);

		/// The navigation mesh
		const NavigationMesh3* _navigationMesh;

		/// The AABBTree.
		AABBTree _tree;

		/// Triangle3 pointer to cell id map.
		glm::GlmMap<const Triangle3*, NavigationMeshCellId> _triangleToCells;
	};

	//*****************************************************************************
	// NavigationMeshCellsAABBTree inline definitions
	//*****************************************************************************

	//-----------------------------------------------------------------------------
	// getNavigationMesh
	//-----------------------------------------------------------------------------
	inline const NavigationMesh3& NavigationMeshCellsAABBTree::getNavigationMesh() const
	{
		return *_navigationMesh;
	}

	//-----------------------------------------------------------------------------
	// getAABBTree
	//-----------------------------------------------------------------------------
	inline const AABBTree & NavigationMeshCellsAABBTree::getAABBTree() const
	{
		return _tree;
	}
}
