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

#pragma once

#include "glmSDKAPI.h"
#include "glmAbstractRoadmapCreator.h"
#include "glmRoadmapCreatorParameters.h"
#include <glmProgress.h>
#include <glmOrientedGraph.h>

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

namespace glm
{
	class Roadmap;
	class SpatialEnvironment;
	class OrientedGraph;
	class ArcDataComputationWorkerThread;

	/**
	* \brief Roadmap creation functor.
	*
	* In most cases users shouldn't use directly this creator, roadmap should be built along
	* a spatial environment using \ref PSSpatialEnvironmentCreator.
	*
	* \ingroup Roadmap
	*
	* \author Golaem <dev@golaem.com>
	*/
	class GLM_SDK_API RoadmapCreator : public AbstractRoadmapCreator
	{
		friend class ArcDataComputationWorkerThread;
	public:

		GLM_CLASS_STAT_ID( glm::MemoryStatIds::Simulation);

		/**
		* \brief Default constructor
		*/
		RoadmapCreator();

		/**
		* \brief Destructor
		*/
		~RoadmapCreator();

		/**
		* \brief Returns the process progress
		* \return the process progress
		*/
		const Progress::SP getProgress() const;

		/**
		* \brief Returns a reference to the process progress
		* \return a reference to the process progress
		*/
		Progress::SP touchProgress();

		/**
		* \name SpatialEnvironment
		* \brief The spatial environment used for the computation.
		*/
		//@{
		const SpatialEnvironment & getSpatialEnvironment() const;
		void setSpatialEnvironment(const SpatialEnvironment & spatialEnvironment);
		//@}

		/**
		* \name Parameters
		*/
		//@{
		const RoadmapCreatorParameters & getParameters() const;
		RoadmapCreatorParameters & touchParameters();
		//@}

	private:

		/**
		* \brief The method to implement to perform computations.
		*/
		bool doComputation(bool& cancel);

		/**
		* \brief This process progress.
		*/
		Progress::SP _progress;

		const SpatialEnvironment* _spatialEnvironment;

		RoadmapCreatorParameters _parameters;

		void addEdgeWaypoints(
			const NavigationMeshEdgeId& edgeId,
			const NavigationMeshCellId& cellId,
			const NavigationMesh3& navmesh,
			glm::PODArray<RoadmapNodeId>& edgeNodes
		);

		RoadmapArc computeArcData(
			const NavigationMeshCellId& cellId,
			const RoadmapNodeId& nidOrigin,
			const RoadmapNodeId& nidExtremity,
			const NavigationMesh3& navmesh) const;

		RoadmapArcId addArc(
			const NavigationMeshCellId& cellId,
			const RoadmapNodeId& nidOrigin,
			const RoadmapNodeId& nidExtremity,
			const NavigationMesh3& navmesh);
	};

	//*****************************************************************************
	// RoadmapCreator inline definitions
	//*****************************************************************************

	//-----------------------------------------------------------------------------
	// getSpatialEnvironment
	//-----------------------------------------------------------------------------
	inline const SpatialEnvironment & RoadmapCreator::getSpatialEnvironment() const
	{
		return *_spatialEnvironment;
	}

	//-----------------------------------------------------------------------------
	// setSpatialEnvironment
	//-----------------------------------------------------------------------------
	inline void RoadmapCreator::setSpatialEnvironment(const SpatialEnvironment & spatialEnvironment)
	{
		_spatialEnvironment = &spatialEnvironment;
	}

	//-----------------------------------------------------------------------------
	// getParameters
	//-----------------------------------------------------------------------------
	inline const RoadmapCreatorParameters & RoadmapCreator::getParameters() const
	{
		return _parameters;
	}

	//-----------------------------------------------------------------------------
	// touchParameters
	//-----------------------------------------------------------------------------
	inline RoadmapCreatorParameters & RoadmapCreator::touchParameters()
	{
		return _parameters;
	}
}
