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

#pragma once

#include "glmSDKAPI.h"
#include "glmPathContext.h"

//golaem core includes
#include "glmAbstractGround.h"

namespace glm
{
	/**
	* \brief Ground relying on the path context's spatial environment.
	*
	* \ingroup ground
	*
	* \author Golaem <dev@golaem.com>
	*/
	class GLM_SDK_API SpatialEnvironmentGround : public AbstractGround
	{
	public:

		GLM_CLASS_STAT_ID( glm::MemoryStatIds::GolaemShared)

		/**
		* \name Construction/Destruction
		*/
		//@{
		SpatialEnvironmentGround(const SpatialEnvironment* spatialEnv = NULL);
		virtual ~SpatialEnvironmentGround();
		//@}

		/**
		* \name Projection retrieval
		*/
		//@{
		bool computeProjection(const Vector3& position, const Vector3& upVector, Vector3& groundPosition, Vector3& groundNormal, float height, GroundCellId& groundCellId, int genericBoneIndex, const void* userPtr) const override;
		//@}

		virtual Vector3 getGroundCellVertex(const GroundCellId& groundCellId, int vertexId) const override;

		/**
		* \name init/update/finish
		*/
		//@{
		void init();
		void update(Time dt);
		void finish();
		//@}

		/**
		* \name Debug geometry
		*/
		//@{
		void computeGeometry(glm::Array<Triangle3>& triangles, glm::Array<Segment3>& normals, const Matrix4& callerMatrixInverse) const;
		//@}

		/**
		* \name Context
		*
		* The path context to use, if none is set, the ground uses the engine manager to retrieve one during initialization.
		*/
		//@{
		const SpatialEnvironment* getSpatialEnvironment() const;
		void setSpatialEnvironment(const SpatialEnvironment* spatialEnv);
		//@}

	private:

		const SpatialEnvironment* _spatialEnv;
	};

	//*****************************************************************************
	// SpatialEnvironmentGround inline definitions
	//*****************************************************************************

	//-----------------------------------------------------------------------------
	// getContext
	//-----------------------------------------------------------------------------
	inline const SpatialEnvironment* SpatialEnvironmentGround::getSpatialEnvironment() const
	{
		return _spatialEnv;
	}

	//-----------------------------------------------------------------------------
	// setContext
	//-----------------------------------------------------------------------------
	inline void SpatialEnvironmentGround::setSpatialEnvironment(const SpatialEnvironment* spatialEnv)
	{
		_spatialEnv = spatialEnv;
	}
}
