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

#pragma once

#include "glmSDKAPI.h"
#include <glmSimulation.h>
#include <glmSimuEntityHandle.h>
#include <glmMap.h>
#include <glmTrafficUtils.h>

namespace glm
{
	class TrafficContext;

	//-------------------------------------------------------------------------
	struct LaneDirection
	{
		enum Value
		{
			FORWARD = 0,
			BACKWARD,
			LS_END
		};
	};

	class OutLane
	{
	public:

		int _roadIndex;
		int _laneIndexFromCenter;
		int _direction; // need this for roads looping on same crossing
	};

	//-------------------------------------------------------------------------
	class Lane
	{
	public:

		Lane();
		~Lane();

		void getSegmentAndRatioFromAbscissa(float abscissa, int& iSegment, float& segmentRatio) const;

		float					_length;
		glm::Array<Vector3>		_positions;
		glm::PODArray<float>	_segmentLength; // length of segment (i, i+1). segmentLength[0] is vertex 0 to 1
		glm::PODArray<float>    _cumulativePreviousSegmentsLengths;
		glm::Array<Vector3>     _rightVector; // ONLY FED FOR ROAD CENTER, other lanes use the same

		PODArray<int> _possibleCrossingOutLaneIndices;
	};

	//-------------------------------------------------------------------------
	class Road
	{

	public:

		Road();
		~Road();

		// definition
		Lane	_roadCenter;
		int		_startCrossingIndex; // crossing or lane is -1
		int		_endCrossingIndex; // crossing or lane is -1
		float	_interlaneSpace;
		float	_laneWidth;
		float	_speedLimit;
		glm::Array<Lane> _lanes[2]; // index 0 is forward, 1 is backward (in curve vertices order)

		// runtime
		GlmMap<TrafficContext*, glm::Array<SimuEntityHandle> >	_carsOnRoad; // a car is on a road, if at least a part of one of its boxes is on the road.
		TrafficLightStatus::Value	_startCrossingLightStatus; // could move to lane if we handle red not on whole line
		TrafficLightStatus::Value	_endCrossingLightStatus;   // could move to lane if we handle red not on single lanes
        bool _startCrossingIsStop = false;
        bool _endCrossingIsStop = false;

		int _carsOnRoadCount; // avoid to go through different contexts
		float _totalCarsLength;
		float _meanCarsSpeed; // need to be / by _carsOnRoad size, used for heuristic

		// this data is useful to compute correct lane choice.
		// this are out lanes as viewed from this road, from oppositeSide most to drive-side most (U Turns are implicit, they always require inner most lane). Thus it s easier to make laneFrominside(0) matchs lowers out lanes
		// lane change is accepted when current "congestionned" if : we can reach same road with a neighbour lane, and if other lane is free to change (no obstacle if we forecast abscissa on the other lane)
		glm::PODArray<OutLane> _startCrossingOutLanes;
		glm::PODArray<OutLane> _endCrossingOutLanes;

        GlmString _name; // debug helper
	};	
}
