#ifndef GRAPHBUILDER_H
#define GRAPHBUILDER_H

#include "SquareGraph.h"
#include <vector>
#include <string>

#include "MemoryManager/debugNew.h"


namespace ground{

	// forward declaration
	class Case;
	/**
	 * classe servant à crée un graph de zones à partir d'une matrice de cases.
	 *
	 * utilise une sorte de pattern <B>FACTORY</B>.
	 *
	 * Cette classe sert à construir un graph de zone carré qui sert par la suite pour trouver des chemins plus rapidement
	 * que par une simple recherche dans la matrice de cases du terrains.
	 *
	 * Elle sert aussi à mettre en place la matrice de ponderation pour le path finder sur matrice.
	 *
	 * On peut aussi charger le contenu du graph depuis un fichier afin de limiter le temps de calcule du graph.
	 */
	class GraphBuilder
	{
	private:
		/**
		 * structure interna servant à stocker les carré formé par l'analyse du terrain
		 */
		struct Square{
			/**
			 * la position X du carré dans la matrice
			 */
			int x;
			/**
			 * la position Y du carre dans la matrice
			 */
			int y;
			/**
			 * la taille des coté du carré.
			 */
			int size;
		};
		/**
		 * le tableau des identifiants
		 */
		int** ident;

		/**
		 * la largeur de la matrice
		 */
		int width;

		/**
		 * la hauteur de la matrice
		 */ 
		int height;

		/**
		 * le vecteur stockant les noeud du graph
		 */
		std::vector<SquareNode*> graph;

		/**
		 * methode permettant de savoir si les bords droit et bas d'un carré sont bien du même type
		 * que la case située en haut à gauche.
		 *
		 * @param matrix : la matrice de cases sur laquelle est effectuée la recherche
		 * @param x : la coordonnée X du point en haut a gauche du carré
		 * @param y : la coordonnée Y du point en haut à gauche du carré
		 * @param size : la taille du carré à tester. si size = 0, le carré n'est composé que de
		 * sa case d'origine.
		 * @return bool : true si les bord du carré sont bien du même type que l'origine
		 * du carré, false sinon.
		 */
		bool isValidSquare(Case*** matrix, int x, int y, int size);

		/**
		 * methode permettant d'appliquer un identifiant à toutes les cases du carré passé en parametre
		 *
		 * @param identVal : l'identifiant à appliquer au carré
		 * @param x : la coordonnée X de l'origine du carré (angle en haut à gauche)
		 * @param y : la coordonnée Y de l'origine du carré
		 * @param size : la taille des cotés du carré ( 0 => carré d'une case)
		 */
		void identifySquare(int identVal,int x, int y, int size);

		/**
		 * methode permettant de crée effectivement le graph en memoire.
		 *
		 * Cette methode initilise les noeud, crée leurs liens et evalue le cout des arc entre les noeuds.
		 * @param matrix : la matrice de case sur laquel sera crée le graph.
		 */
		void createGraph(Case*** matrix);

		/**
		 * methode permettant de trouver dans de graph et la matrice d'identifiant les noeud voisin du noeud passé
		 * en parametre et de crée les liens entre ces noeuds.
		 * 
		 * @param node : le noeud pour lequel on souhaite trouver les voisins.
		 */  
		void foundNeighbour(SquareNode* node);

	public:

		/**
		 * constructeur par defaut
		 */
		GraphBuilder(void);

		/**
		 * destructeur par defaut.
		 */
		~GraphBuilder(void);

		/**
		 * methode permettant de calculer le graph de zones sur la matrice de cases passée en parametres.
		 *
		 * @param matrix : la matrice de cases sur laquelle sera effectuée le decoupage en zones.
		 * @param width : la largeur de la matrice
		 * @param height : la heuteur de la matrice.
		 */
		void computeZones(Case*** matrix,int width,int height);

		/**
		 * methode permettant de nettoyer le graph de la memoire.
		 */
		void clearGraph();

		/**
		 * methode permettant de sauvegarder le graph dans un fichier pouvant etre charger ulterieurement
		 * avec la methode loadFromFile()
		 *
		 * @param file : le chemin du fichier dans lequel sera sauvegardé le graph
		 */
		void saveToFile(std::string file);

		/**
		 * methode permettant de charger un graph a partir d'un fichier.
		 *
		 * @param file : le chemin du fichier a partir du quel on va vharger le graph
		 * @param matrix : la matrice de cases sur laquelle sera reconstruit le graph
		 * @param width : la largeur de la matrice
		 * @param height: la heuteur de la matrice
		 */
		void loadFromFile(std::string file, Case*** matrix, int width, int height);

		/**
		 * methode permettant de crée une copie du graph
		 *
		 * @return Graph : la copie du graph crée par le GraphBuilder. Cette copie doit etre detruite par
		 * l'utilisateur a l'aide de l'operateur delete
		 */ 
		Graph * createGraph();

		/**
		 * methode permettant d'initialiser la matrice de ponderation à partire d'un chemin trouvé dans le graph.
		 *
		 * @param matrix : la matrice de float servant de ponderatuer pour la pathfinder sur matrice
		 * @param path : le chemin trouvé dans le graph.
		 */
		void setupPonderationMatrix(float** matrix, std::vector<GraphNode*>& path);

		/**
		 * methode servant à afficher le graph pour le debuger.
		 * @param caseSize : la taille d'une case de la map.
		 */
		void drawGraph(int caseSize);
	};

};// namespace ground

#include "MemoryManager/debugNewOff.h"

#endif
