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

#pragma once

#include "glmArray.h"
#include "glmPODArray.h"
#include "glmVector3.h"
#include "glmSegment3.h"
#include "glmMutex.h"
#include "glmSDKAPI.h"

#include "glmTrafficVehicle.h"

namespace glm
{

	// must recycle segments to avoid too much allocations
	// each chunk can be a crossing trajectory or a lane trajectory
	//-------------------------------------------------------------------------
	class GLM_SDK_API CrossingTrajectory
	{
	public:
		GLM_CLASS_STAT_ID( glm::MemoryStatIds::Simulation);

		CrossingTrajectory();
		~CrossingTrajectory();

		// return false if neither front nor back are on the crossing (no segemnt to test)
		void getPointAtAbscissa(float abscissa, Vector3& point);
		void getForwardAtAbscissa(float abscissa, Vector3& forward); // this is the forward segment where this asbcissa is lying (or start / end if none)
		int getTrajectorySegmentForAbscissa(float abscissa);
		bool getVehicleSegmentAtAbscissa(float abscissa, Segment3& segment, Vehicle& vehicleProps);
		void clear();
		void computeForwards();

		Array<Vector3> _trajectoryVertices;			// n vertices
		Array<Vector3> _trajectoryForwards;			// n-1 "forwards"
		PODArray<float> _trajectorySegmentLengths;	// n-1 segments length
		PODArray<float> _cumulativePreviousSegmentsLengths;	// n-1 previous segments length
		float _trajectoryAbscissa; // the trailer box abscissa on the trajectory
		float _trajectoryLength;

		float _crossingSpeed; // depends on the in/out angle of this crossing trajectory, max speed if ahead, or respect turning speed rules 

		// runtime helpers
		//Vector3 _endForwardNormalized;
		//Vector3 _startForwardNormalized;

		//class ConditionalWaitPosition
		//{
		//public:
		//	float _abscissa;
		//	TrafficContext _otherTrafficContext;
		//	SimuEntityHandle _otherHandle; // must compute back abscissa from 
		//	float _otherBackAbscissaTreshold; // when other back abscissa reach this treshold, it is safe to continue to next
		//};

		//glm::PODArray<ConditionalWaitPosition> _waitPositions; // use from lowest abscissa to highest. set does not handle multiple entries
		//glm::PODArray<> _otherCarsBefore;

		//bool _authorized;

		int _crossingIndex;
	};

	//-------------------------------------------------------------------------
	class GLM_SDK_API CrossingTrajectoryProvider
	{
	public:
		GLM_CLASS_STAT_ID( glm::MemoryStatIds::Simulation);

		CrossingTrajectoryProvider();
		~CrossingTrajectoryProvider();

		CrossingTrajectory* getTrajectory();
		void recycleTrajectory(CrossingTrajectory* chunk);
		void clearRecycledTrajectories();

		glm::SpinLock			_chunksLock;
		PODArray<CrossingTrajectory*> _availableChunks;
		PODArray<CrossingTrajectory*> _allChunks;
	};

	//-------------------------------------------------------------------------
	GLM_SDK_API CrossingTrajectoryProvider& getCrossingTrajectoryProvider();
}