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

#pragma once

#include "glmSDKAPI.h"
#include "glmMemory.h"
#include "glmArray.h"
#include "glmTriangle3.h"
#include "glmSensorFilter.h"
#include "glmFastBoundingBox.h"
#include "glmVoxelField.h"

namespace glm
{
	class AABBTree;
	class SensorFilter;
	struct SensorDetectionType
	{
		enum Value
		{
			ENTITY = 0,
			NAVOBSTACLE,
			BOTH,
			END
		};
	};

	// Sensor Filter Type
	struct SensorFilterType
	{
		enum Value
		{
			OP_AND = 0,
			OP_OR,
			OP_NOT,
			MAX_COUNT,
			NAV_VIS,
			SORT_DIST,
			ENTITY_TYPE,
			PP_ATTRIBUTE,
			GLM_ATTRIBUTE,
			EXTERNAL_ENTITY,
			END
		};
	};

	class GLM_SDK_API Sensor
	{
	public:

		GLM_CLASS_STAT_ID( glm::MemoryStatIds::Simulation);

		static const char*	_activeSensorsKBEntryName;
		static int64_t		_activeSensorsKBHashKey;

		static const char*	_timeSinceSensorUpdateKBEntryName;
		static int64_t		_timeSinceSensorUpdateKBHashKey;

        glm::GlmString _name = "Default Sensor";
        uint32_t _displayColor = 0xFFFFFFFF;
        glm::Array<glm::Array<glm::Triangle3>> _detectionGeo;
        unsigned int _maxVoxelCount = 10;
        VoxelField _voxelField;

        glm::Array<Vector3> _detectionGeoVoxelCenters;

        glm::Array<Voxel> _voxelsToDisplay;

        SensorDetectionType::Value _detectionType = SensorDetectionType::ENTITY;
        float _detectionPeriod = 0.249f;

        //alignement with entity parameters
        float _alignementWithMoveOrientationSpeedThreshold = 1.f; //speed at which sensor is aligned on the move orientation rather than the body orientation
        bool _alignementUseDesiredMoveOrientation = false;        //using the desired move orientation instead of the move orientation
        bool _alignementOrientationIn2d = false;                  //if the sensor is aligned with the heading orientaiton only or full 3d orientation

        glm::PODArray<SensorFilter*> _topLevelFilters;
        glm::PODArray<SensorFilter*> _allFilters;

        Sensor();
        ~Sensor();

        void initFromGeometry();

        void initFilters(const glm::GlmString& filtersStr);

    protected:
        static const char* _objectIndexKBPrefix;
        static const char*	_objectIdKBPrefix;
		static const char*	_objectDistKBPrefix;
        static const char* _closestVoxelToPerceivedObjectKBPrefix;
        static const char* _closestPerceivedObjectVoxelKBPrefix;

        friend class PerceptionContext;
    };
}
