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

#pragma once

#include "glmSDKAPI.h"
#include "glmNavigationMeshLocation.h"
#include "glmRoadmapNode.h"
#include "glmRoadmapArc.h"

//golaem core includes
#include <glmExtendedOrientedGraph.h>
#include "glmPODArray.h"

namespace glm
{
	class SpatialEnvironment;

	/**
	* \brief A generic asynchronous spatial environment roadmap query
	*
	* \ingroup PathLib
	*
	* \author Golaem <dev@golaem.com> 
	*/
	class GLM_SDK_API AbstractRoadmapQuery
	{
	public:

		GLM_ABSTRACTCLASS_STAT_ID( glm::MemoryStatIds::Simulation)

		/**
		* \brief Possible statuses of a query
		*/
		struct GLM_SDK_API GlmQueryStatus
		{
			enum Value
			{
				STOPPED,
				RUNNING,
				SUCCESS,
				FAILURE,
				END
			};
		};

		/**
		* \brief Constructor
		* \param spatialEnvironment The spatial environment on which the query is performed.
		*/
		AbstractRoadmapQuery(const SpatialEnvironment& spatialEnvironment);

		/**
		* \brief Destructor.
		*/
		virtual ~AbstractRoadmapQuery() = 0;

		/**
		* \brief Retrieve the spatial environment on which the query is performed.
		*/
		virtual const SpatialEnvironment& getSpatialEnvironment() const;

		/**
		* \brief Returns the status of the query
		*/
		virtual const GlmQueryStatus::Value& getStatus() const;

		/**
		* \brief Launches the execution of the query
		*/
		virtual void doIt(bool continueFromLastQuery = false) = 0;

		/**
		* \brief Resets the status of the query and the query graph
		*/
		virtual void reset();

		/**
		* \brief Returns the extened graph for the query
		*/
		const ExtendedOrientedGraph& getQueryGraph() const;

	protected:

		/**
		* \brief Connects a location to the query graph if possible
		* The location must be defined in the same spatial environment as the query, and it must be valid
		* \param[out] locationWaypointId The waypoint id of the location in the query graph
		*/
		virtual bool connectToGraph(const NavigationMeshLocation& location, RoadmapNodeId& locationWaypointId);

		/**
		* \brief Connects two nodes in the query graph
		*/
		virtual bool connectWaypoints(const RoadmapNodeId& waypointId1, const RoadmapNodeId& waypointId2, const NavigationMeshCellId& cellId/*, bool useThreadSafeGraph = true*/);

		glm::PODArray<RoadmapNodeId> _nodes; // working data, keeps it allocated to avoid realloc at each planification

		/// The spatial environment for which the query is defined.
		const SpatialEnvironment* _spatialEnvironment;

		/// The extened graph for the query
		ExtendedOrientedGraph _queryGraph;

		/// The status of the query
		GlmQueryStatus::Value _status;
	};
}
