var map,infoWindows;
var pagesCluster = [];
var listPoly = new Array();
var listExtendedPoly = new Array();
var listMarker = new google.maps.MVCArray();
var returnedData;
var markerCluster;
var clusterInfoWindows;
/**
 * Définition de styles personalisés pour les clusters
 */

var styles = new Array();
styles.transac = [{
  url: '/media/images/moteur_ggmaps/carre_bleu_petit.png',
  height: 20,
  width: 20,
  textColor: '#074F8E',
  textSize: 10
},
{
  url: '/media/images/moteur_ggmaps/carre_bleu.png',
  height: 25,
  width: 25,
  textColor: '#074F8E',
  textSize: 11
},
{
  url: '/media/images/moteur_ggmaps/carre_bleu_grand.png',
  height: 30,
  width: 30,
  textColor: '#074F8E',
  textSize: 12
}];

/**
 * Fonction d'initialisation de la map
 * Paramètres :
 * adresse -> Point sur lequel sera centrée la map lors de son chargement
 * div -> div dans laquelle la map va se charger
 */

function initialize(adresse,div) {
	var i = 0;
	var centre = new google.maps.Geocoder();
	var centreMap;
	// Définition de options de la map
	var myOptions = {
	  zoom: 12,
	  maxZoom: 14,
	  streetViewControl: false,
	  panControl: false,
    mapTypeId: google.maps.MapTypeId.ROADMAP
	};
	map = new google.maps.Map(document.getElementById(div),myOptions);// initialisation de la map
	// Calcul du centre de la map
	var reg1 = new RegExp("^([0-9]*)(\.)([0-9]*),([0-9]*)(\.)([0-9]*)$");
  if(reg1.test(adresse)){
    var elem = adresse.split(',');
 		map.setCenter(new google.maps.LatLng(parseFloat(elem[0]),parseFloat(elem[1])));
  }else{
    var centre = new google.maps.Geocoder();
    centre.geocode({
		  address: adresse
		},
		function(results, status){
		  if (status == google.maps.GeocoderStatus.OK){
			  window.centre = results[0].geometry.location;
      }
      else{
        alert("Erreur dans la fonction Geocode : " + status);
      }
		});
		map.setCenter(window.centre);
		window.centre = null;
}
	/*centre.geocode({
		address: adresse
		},
		function(results, status){
			centreMap = results[0].geometry.location
			map.setCenter(centreMap);
		}
	);*/
	// Initialisation des cluster qui contiendront les biens à afficher
	markerCluster = new MarkerClusterer(map,"",{
	  minimumClusterSize: 1,
	  averageCenter: true,
	  zoomOnClick: false,
	  maxZoom:14,
	  gridSize: 50
	  // Définition d'un style par défaut
 	  /*styles: [{
        url: '/media/images/moteur_ggmaps/carre_clair.png',
        height: 25,
        width: 25
      }]*/
  });

  // Récupération de coordonnées des différents secteur definis dans l'admin et création des polygones
	$.ajax({
		async: false,
		type:"POST",
		url:"/fr/admin/recup-secteurs",
		success: function(retour){
			retour = eval ('(' + retour + ')');
			for(i; i<retour.length; i++) {
				createPoly(retour[i]);
			}
		}
	});
}

/**
 * Fonction qui va gérer le centrage et le niveau de zoom de la map en fonction des critères choisis dans le moteur pour que les biens soit visibles
 */

function centerMap(centre){
  map.panTo(centre);
}

/**
 * Fonction de création de la fenêtre infos bulle au clic sur un cluster
 * Paramètres :
 * cluster -> est le cluster sur lequel l'evenement "clic" a été déclenché et pour lequel l'info bulle doit apparaître
 * type -> est le type de recherche (transac, loc etc ...) qui va permettre au modèle de savoir quelle table de la base il doit interroger
 */
function infosCluster(cluster,type,lang){
  var lat,lon,content,options;
  var biens = [];
  pagesCluster = [];

  // On ferme les infos bulles qui sont ouvertes
  if(typeof(clusterInfoWindows) != 'undefined'){
    clusterInfoWindows.close();
  }

  // On stock les title des marqueur du cluster (contenant les ref des biens) dans un tableau
  for(var i = 0; i<cluster.markers_.length; i++){
    pagesCluster.push(cluster.markers_[i].title);
  }

  // Interrogation du controleur "clusterInfoWindow" qui va retourner le contenu de l'info bulle en fonction de la liste des ref des biens présents dans le cluster
  $.ajax({
    async: false,
    type:"POST",
    url: "/" + lang + "/ggMaps_ajax/clusterInfoWindow",
    data:"refs=" + pagesCluster.to_json() + "&type=" + type,
    success: function(retour){
      content = retour;
    }
  });

  // Definition des options, création et ouverture de l'infobulle
  options = {
		position: cluster.getCenter(),
		content: content
	};
	clusterInfoWindows = new google.maps.InfoWindow(options);
	clusterInfoWindows.open(map);
}

/**
 * Fonction qui va créer les polygones sur la map
 * Paramètres :
 * infos -> contient les informations nésséssaires à la création d'un poly notamment la liste des points qui composent son perimètre et son identifiant
 */
function createPoly(infos){
	var listPoints = json2LatLng(infos.points);
	var polyPath = new google.maps.MVCArray();
	var i = 0;

  // Création d'un tableau contenant les coordonnées des points qui composent le contour du polygone
	for(i; i<listPoints.length; i++) {
		polyPath.push(new google.maps.LatLng(listPoints[i][0],listPoints[i][1]));
	}

	// Création du polygone et stockage de celui ci dans un tableau dont le clé sera son id en attendant d'etre affiché
	listPoly[infos.id] = new google.maps.Polygon({
		path: polyPath,
	    strokeColor: "#FF0000",
	    strokeOpacity: 0.8,
	    strokeWeight: 2,
	    fillColor: "#FF0000",
	    fillOpacity: 0.35
	});
}

/**
 * Fonction qui va faire apparaitre un ou plusieur polygones sur la map
 * Parametres :
 * listId -> liste des Id du ou des polygones a faire apparaitre sur la map
 */
function displayPoly(listId){
	var i = 0;
	var y = 0;
	var poly;
	for(y; y<listPoly.length; y++) {
		if(listPoly[y]) {
			if(listId.length>0) {
				if(listId[0] == "all") {
					listPoly[y].setMap(map);
				}else {
					for(i; i<listId.length; i++) {
						if(listId[i]==y) {
							listPoly[y].setMap(map);
							break;
						}else {
							listPoly[y].setMap(null);
						}
					}
					i = 0;
				}
			}else {
				listPoly[y].setMap(null);
			}
		}
	}
}

/**
 * Fonction qui va créer la version étendue d'un ou plusieur polygones dans le cas ou l'on souhaite afficher les biens d'un secteur plus x km
 * Paramètres :
 * listId -> Liste des id du ou des polygones pour lequels on souhaite calculer la version étendue
 * distance -> la distance en metres qu'on ajoutera au rayon du polygone pour obtenir la version etendue
 * TODO : revoir cette fonction car elle ne fonctionne pas correctement en cas d'angle concave, c'est a dire qui pointes vers l'interieur du polygone
 */
function extendPoly(listId,distance){
	var newPath = new Array();
	listExtendedPoly = new Array();
	for(var y=0; y<listPoly.length; y++) {
		if(listPoly[y]) {
			if(listId.length>0) {
				for(var i=0; i<listId.length; i++) {
					if(listId[i]==y) {
						var centre = listPoly[y].getBounds().getCenter();
						var chemin = listPoly[y].getPath();
						chemin.forEach(function(element,index) {
							var angle = google.maps.geometry.spherical.computeHeading(centre,element);
							var nouvo = google.maps.geometry.spherical.computeOffset(element, distance, angle);
							newPath.push(nouvo);
						});
						listExtendedPoly[i] = new google.maps.Polygon({//listId[i]
							path: newPath
						});
						newPath = new Array();
					}
				}
			}
		}
	}
}

/**
 * Fonction qui créé les marqueurs représentants les biens sur la carte
 * Paramètres :
 * lat -> lattitude du marqueur
 * lon -> longitude du marqueur
 * infos -> contient la référence du bien et servira de title au marqueur
 * @contentInfo -> paramétre optionnel qui ne sert que dans le cas ou l'on utilise pas le clustering, contient le code html contenu dans l'info bulle
 * @style -> paramétre optionnel qui ne sert que dans le cas ou l'on utilise pas le clustering, permet de donner un style au marqueur (exemple : coup de coeur, neuf, etc ...)
 */
function createMarker(lat,lon,infos,contentInfo,style) {
	var marker;
	var options = {
		//map: map,//INUTILE sauf si on utilise pas le clustering
		position: new google.maps.LatLng(lat,lon),
		flat: true,
		visible: false,//UNIQUEMENT avec clustering
		title: infos
	};
	marker = new google.maps.Marker(options);
	/*****************************************************************************/
	/** A utiliser si on desire l'affichage des marker sans clustering ou les 2 **/
	/*****************************************************************************/
	/*if(style){
	  marker.setIcon(style);
	}
	google.maps.event.addListener(marker, 'click', function(e) {
		if(infoWindows != null) {
			infoWindows.close();
		}
		infoWindows = new google.maps.InfoWindow({
			position:marker.getPosition(),
			content: contentInfo
		});
		infoWindows.open(map);
	});*/
  /***********************************************************************/
	listMarker.push(marker);//On stock tous les marqueurs dans un tableau
	return marker;
}

/**
 * Fonction qui va faire disparaitre les marqueurs de la map et vide le tableau de marqueur
 */
function deleteMarkers() {
	listMarker.forEach(function(marker,index) {
		marker.setMap(null);
	});
	listMarker.clear();
}

/**
 * Fonction qui va mettre a jour la combo des ville en fonction du secteur choisi par l'internaute
 * Paramètres :
 * idCombo -> C'est l'Id du combo ville que l'on va remplacer par le nouveau
 * listeVille -> c'est la liste complète des villes présentes dans la base
 * listIdPoly -> c'est la liste des Id du ou des secteurs choisi par l'internaute
 */
function updateComboVille(idCombo,listeVille,listIdPoly){
	var i = 0;
	var options = "<option value=\"\" selected=\"selected\">Choix de la ville</option>";
	var latLng,y;
	var villes = new Array();
	for(i; i<listeVille.length; i++) {
		latLng = new google.maps.LatLng(listeVille[i].LAT,listeVille[i].LON);
		y = 0;
		if(listIdPoly.length>0) {
			for(y; y<listIdPoly.length; y++) {
				if(listIdPoly[y] != "" && listPoly[listIdPoly[y]].contains(latLng)) {
					if(!villes.in_array(listeVille[i].VILLE)) {
						villes.push(listeVille[i].VILLE);
						options = options + "<option value=\"" + listeVille[i].VILLE + "\">" + listeVille[i].VILLE + "</option>";
					}
				}else if(listIdPoly[y] == ""){
			    options = options + "<option value=\"" + listeVille[i].VILLE + "\">" + listeVille[i].VILLE + "</option>";
				}
			}
		}else {
			options = options + "<option value=\"" + listeVille[i].VILLE + "\">" + listeVille[i].VILLE + "</option>";
		}
	}
	$(idCombo).html(options);
}

/**
 * Fonction qui affiche sur la map tous les polygones présent dans un groupe de secteur
 * id -> Identifiant du groupe de secteur à afficher
 */
function getSecteursGroupe(id) {
  $.ajax({
    url: "admin/get_secteurs_groupe",
    type: "POST",
    data: "idGroupe=" + id,
    success: function(retour){
      var secteur = eval ( "(" + retour + ")" );
      displayPoly(secteur);
    }
  });
}

/**
 * Fonction qui transforme en tableau de coordonnées (lat,lng) les infos des points composant le contour du polygone qui remontent de la base.
 * Paramètres :
 * json -> données remontant de la base, ce sont la liste des points qui composent le pourtour du polygone
 */
function json2LatLng(json) {
	var listPoints = [];
	var stringPoints = json;
	var points = stringPoints.split(';');
	var point;
	for(var i = 0; i<points.length; i++){
		point = points[i].split('|');
		listPoints[i] = new Array(point[0].replace(",","."),point[1].replace(",","."));
	}
	return listPoints;
}

/**
 * Fonction qui va dessiner un cercle sur la map
 * INUTILISE pour l'instant mais prevu pour servir dans l'affichage des services de proximités
 */
function drawCircle(adresse,rayon){
  var cercle = new google.maps.Circle();
 	var centre = new google.maps.Geocoder();
  var centreCercle;

  centre.geocode({
		address: adresse
		},
		function(results, status){
			centreCercle = results[0].geometry.location
			cercle.setCenter(centreCercle);
		}
	);

  cercle.setOptions({
    fillColor: "#0000FF",
    fillOpacity: 0.2,
    radius:rayon,
    map: map,
    strokeColor: "#000000",
    strokeOpacity: 0.4,
    strokeWeight: 1
  });
}
