#ifndef VISIBILITYCHECKER_H
#define VISIBILITYCHECKER_H

#include <vector>
#include "VisibilityArea.h"
#include "GroundMap.h"

#include "MemoryManager/debugNew.h"


namespace ground{
	/**
	 * classe gerant le calcule des zone de vision des unitée.
	 *
	 * Cette classe prend en parametre des instance de VisibilityArea et calcule une matrice de visibilité
	 * en fonction des parametre des VisibilityArea.
	 *
	 * Avant d'utiliser le VisibilityChecker, il faut imperativement lui donner les parametres de la carte,
	 * c'est à dire sa longueur et sa largeur, avec la methode setMatrixParameters().
	 * Une fois ces parametres passé au VisibilityChecker, on peut utiliser la methode checkVisibility() pour
	 * calculer la matrice de visibilité.
	 * 
	 * Une utilisation standard du VisibilityChecker donne donc le code suivant :
	 * <PRE>
	 * ground::VisibilityChecker visibilityChecker;
	 * std::vector<ground::VisibilityArea*> visibilityAreaVector;
	 * visibilityChecker.setMatrixParameters(mapWidth,mapHeight);
	 * [...] // a lots of code [...]
	 * // ici bien s'assurer que la matrice est bien une matrice de bool[mapWidth][mapHeight] !!!
	 * visibilityChecker.checkVisibility(visibilityMatrix,visibilityAreaVector);
	 * // maintenant, la matrice est calculée, les cases à false ne sont pas visible, alors que celles a
	 * // true le sont.
	 * </PRE>
	 */
	class VisibilityChecker
	{
	private:
		/**
		 * la largueur de la matrice de visibilité
		 */
		int mapWidth;
		/**
		 * la hauteur de la matrice de visibilité.
		 */
		int mapHeight;
		/**
		 * la hauteur precedante durant l'analyse d'un rayon lors du ray tracing.
		 */
		float previousHeight;
		/**
		 * le signe precedent de la pente lors de l'analyse d'un rayon du ray tracing. permet de savoir
		 * si on change de sens dans la pente ou pas.
		 */
		int previousSigne;
		/**
		 * la matrice de visibilitée qu'on calcule.
		 */
		bool ** visibilityMatrix;
		/**
		 * methode permettant de nettoyer la matrice avant de commencer le calcule de visibilité.
		 */
		void clearMatrix();

		/**
		 * methode permettant de calculer la visibilitée pour une entité donné en prenant en compte les bords autour de l'entité.
		 * @param entity : l'entité pour laquelle on va calculer la visibilité.
		 */
		void computeVisibility(VisibilityArea* entity);
		/**
		 * methode permettant de calculer le ray tracing pour une unitée donnée.
		 *
		 * Cette methode differe de computeVisibility par le fait qu'elle n'effectue que le ray tracing, sans prendre en compte
		 * les cases autour de l'entité.
		 * @param entity : l'entité pour laquelle on va effectuer le ray tracing.
		 */
		void rayTrace(VisibilityArea * entity);
		/**
		 * methode permettant de rendre visible les cases autour d'une entité donnée.
		 * @param entity : l'entité pour laquelle on souhaite rendre visible les cases adjacentes.
		 */
		void showBorders(VisibilityArea * entity);
		/**
		 * methode permettant de determiné si la case donnée en parametre bloque la vue ou pas.
		 * @param x : la coordonnée x de la cases à tester.
		 * @param y : la coordonnée y de la cases à tester.
		 * @param baseHeight : la hauteur de depart de l'entité.
		 */
		bool checkPassable(float x,float y, float baseHeight);
	public:
		/**
		 * constructeur par defaut.
		 */ 
		VisibilityChecker(void);
		/**
		 * destructeur par defaut.
		 */
		~VisibilityChecker(void);
		/**
		 * methode permettant de calculer la matrice de visibilitée en fonction d'un vecteur de VisibilityArea.
		 *
		 * Attention a bien vous assurer d'avoir bien appelé la methode setMatrixParameters() avant d'appeler cette
		 * methode, et aussi, bien s'assurer que la matrice passé en parametres correspond bien au parametres passé 
		 * à la methode setMatrixParameters().
		 * @param matrix : tableau à 2 dimensions representant la matrice de visibilitée. à la fin de la methode, les
		 * cases de la matrice a false sont non visible, alors que les cases à true sont considérées comme etant visibles.
		 * @param entity : vecteur de VisibilityArea representant les entité qui observent la carte.
		 */
		void checkVisibility(bool** matrix,std::vector<VisibilityArea*>& entity);

		/**
		 * methode permettant de definir les parametre de la carte sur laquel sera effectué les calcules.
		 * 
		 * Doit imperativement etre appelé avant tout appel à la methode checkVisibility.
		 * @param width : la largueur de la carte.
		 * @param height : la hauteur de la carte.
		 */
		void setMatrixParameters(int width,int height);
	};

};// namespace ground

#include "MemoryManager/debugNewOff.h"

#endif
