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

#pragma once

#include "glmIOrientedGraph.h"

#include "glmRoadmapNode.h"

namespace glm
{
	/** 
	* \brief A generic oriented graph.
	*
	* \ingroup graphs
	* 
	* \see IOrientedGraph
	*
	* \param int The class defining node identifier (should be defined using GLM_DECLARE_CUSTOM_INDEX).
	* \param int The class defining arcs identifier (should be defined using GLM_DECLARE_CUSTOM_INDEX).
	* \param RoadmapNode The class used for the data associated to nodes.
	* \param RoadmapArc The class used for the data associated to arcs.
	*
	* \author Golaem <dev@golaem.com>
	*/
	class GLM_SDK_API OrientedGraph : public IOrientedGraph
	{

	public:

		GLM_CLASS_STAT_ID( glm::MemoryStatIds::Simulation)

		/** 
		* \brief Default constructor.
		*/
		OrientedGraph();

		/** 
		* \brief Copy constructor
		*/
		//OrientedGraph(const OrientedGraph & graph);

		/** 
		* \brief Virtual destructor
		*/
		virtual ~OrientedGraph();

		/** 
		* \brief Affectation
		*/
		//OrientedGraph & operator= (const OrientedGraph & graph);

		/** 
		* \brief Clear the graph structure and the attached data of the current instance.
		*/
		void clear();

		/** 
		* \name Nodes
		*/
		//@{
		void findNextFreeNode();
		unsigned int getNbNodeIds() const;
		bool hasNode(const int & nodeId) const;
		int addNode(const RoadmapNode& data);
		void removeNode(const int& nodeId);
		const RoadmapNode& getNode(const int& nodeId) const;
		const glm::PODArray<int> & getNodeSuccessors(const int & nodeId) const;
		const glm::PODArray<int> & getNodePredecessors(const int & nodeId) const;
		//@}

		// for unitTest only
		unsigned int getNbNodes();
		unsigned int getNbArcs();

		/** 
		* \name Arcs
		*/
		//@{
		void findNextFreeArc();
		unsigned int getNbArcIds() const;
		bool hasArc(const int & arcId) const;		
		int addArc(const int& origin, const int& extremity, const RoadmapArc & data);
		void removeArc(const int& arcId);
		const RoadmapArc & getArc(const int& arcId) const;
		int getArcOrigin(const int & arcId) const;
		int getArcExtremity(const int & arcId) const;
		int retrieveArc(const int & origin, const int & extremity) const;
		//@}

		struct ArcData
		{
			int _origin;
			int _extremity;
			RoadmapArc _data;
		};

	protected:
		glm::Array<RoadmapNode> _nodeData;
		glm::Array<ArcData> _arcData;

		// CONSTRUCTION ONLY, must be trimmed before serializing
		glm::Array< glm::PODArray<int> > _successors;	// arrays of outgoing ArcIds
		glm::Array< glm::PODArray<int> > _predecessors;	// arrays of incoming ArcIds
		//glm::PODArray<int> _freeNodeId;
		//glm::PODArray<int> _freeArcId;
		glm::PODArray<bool> _validNodeId;
		glm::PODArray<bool> _validArcId;

		int _firstFreeNodeId;
		int _firstFreeArcId;

	private:
		GLM_DISALLOW_COPY_AND_ASSIGN( OrientedGraph );
	};
}

