// RQGMap.js
// 
// Dependency : 
//	- RQCommon.js (RQDelegate)

RQGMap = 
{
	__DEBUG__:false,

	gmap : null,
	geocoder : null,
	locations : null,
	icons : null,
	gbounds : null,
	nbTriesMax:10,
	cbAllPointsFound:null,
	cbCacheGeocode:null,
	cbClickMarker:null,
	iCurrentLocationFind:0,
	nbQueries:0,

	/*
		Function: create
			Creates an instance of GMap2 ( http://code.google.com/apis/maps/documentation/reference.html#GMap2 )
			and an instance of GClientGeocoder ( http://code.google.com/apis/maps/documentation/reference.html#GClientGeocoder )
			
		Parameters:
			mapDiv - String / the id of the div where the map is displayed
	*/
	create : function(mapDiv)
	{
		this.gmap = new GMap2(document.getElementById(mapDiv));		
		//this.gmap.addControl(new GSmallZoomControl3D());
		this.gmap.addControl(new GLargeMapControl3D());
		//this.gmap.addControl(new GLargeMapControl());
		//this.gmap.addControl(new GMapTypeControl());
		this.gmap.setCenter(new GLatLng(47.15984, 2.988281), 5);
		this.gbounds = new GLatLngBounds();
		this.geocoder = new GClientGeocoder();
	},

	/*
		Function: addLocation
			
		Parameters:
			where - Object

		See Also : 
			<showLocations>
	*/
	addLocation : function(where)
	{
		if (!this.locations)
			this.locations = Array();	
		this.locations.push( {id:this.locations.length, where:where, marker:null,found:false,nbTry:0} );
	},
	
	/*
		Function: addIcon
			
		Parameters:
			icon - Object / infos whose properties match GIcon class ones. 
	
	*/
	addIcon : function(icon)
	{
		if (!this.icons)
			this.icons = Array();	
		var myIcon = this.icons[icon.id] = new GIcon();
		for (var p in icon)
			myIcon[p] = icon[p];
	},
	/*
		Function: findLocation
			Finds a location using the geocoder instance.
		
		Parameters:
			location - Object to be parsed by the geocoder.
	*/
	findLocation : function(location)
	{
		if (location.where.lat && location.where.lng)
		{
			this.addMarker(location, location.where.lat,location.where.lng, location.where.icon);
			this.foundLocation(location);
			this.findNextLocation();
		}
		else
		if (location.where.query)
		{
			this.nbQueries++;
			if (this.__DEBUG__)
				console.log("Looking for "+location.where.query+",nbQueries="+this.nbQueries);
			this.geocoder.getLocations(location.where.query, function(response){ RQGMap.geocoderResponseCb(response,location); } );
		}
	},
	
	findNextLocation : function()
	{
		if (this.iCurrentLocationFind<this.locations.length-1)
			this.findLocation(this.locations[++this.iCurrentLocationFind]);
		else
			this.checkAllLocationsFound();			
	},
	
	foundLocation : function(location)
	{
		location.found	= true;
	},
	
	/*
		Function: showLocations
			Finds locations and set a marker on the map.
	*/
	showLocations : function()
	{
		if( this.locations)
		this.findLocation(this.locations[this.iCurrentLocationFind]);
	},

	/*
		Function : centerAroundLocations
			Once every location was retrieved, center the map around them
	*/
	centerAroundLocations : function(shift)
	{
		this.gmap.setCenter(this.gbounds.getCenter(),this.gmap.getBoundsZoomLevel(this.gbounds)+(shift?shift:0));
	},

	/*
		Function : addMarker
			Adds a marker to the map
			
		Parameters : 
			lat - latitude 
			lng - longitude
			iconId - id of the icon. if undefined or not existing, default GIcon is drawn
	*/
	addMarker : function(location,lat,lng,iconId)
	{
		var point	= new GLatLng(lat, lng);
		location.marker = this.createMarker(location, point,iconId);

//		GEvent.addListener(location.marker, "mouseover",	function(){RQGMap.gmap.getInfoWindow().reset(location.marker.getLatLng(),0,new GSize(50,50));});
//		GEvent.addListener(location.marker, "mouseout",		function(){RQGMap.gmap.getInfoWindow().hide();});

		this.gmap.addOverlay( location.marker );
		this.gbounds.extend(point);
		return location.marker;
	},

	clickMarker : function()
	{
	},


	/*
		Function : createMarker
		Returns : 
			GMarker instance
		Parameters : 
			point - location of the marker
			iconId - its icon
	*/
	createMarker : function(location,point,iconId)
	{
		// Choose default
		var icon = G_DEFAULT_ICON;
		if (iconId==undefined && this.icons)
			icon = this.icons[0];
		if (iconId != undefined && iconId<this.icons.length)
			icon = this.icons[iconId];
		//console.log(location.where.userData);
		return new GMarker(point,{icon:icon,title:location.where.title ? location.where.title:""});
	},
	
	/*
		Function : geocoderResponseCb
			Called automatically
			
		Parameters : 
			response - response code
	*/
	geocoderResponseCb : function(response,location)
	{
		if (!response || response.Status.code != 200) 
		{
			console.log("Sorry, we were unable to geocode that address("+location.where.query+"), nbTry="+location.nbTry+",status="+response.Status.code);

			location.nbTry++;
			if (location.nbTry<=this.nbTriesMax)
			{
				setTimeout(function(){RQGMap.findLocation(location)}, 5000);
			}
			else
			{
//				console.log("Removing "+location.where.query+", remaining "+this.locations.length);
//				var pos = this.locations.indexOf( location );
//				pos > -1 && this.locations.splice( pos, 1 );
			}
		} 
		else 
		{
			// Parse result
			place = response.Placemark[0];
			// Place a marker
			this.addMarker(location, place.Point.coordinates[1], place.Point.coordinates[0], location.where.icon);
			this.foundLocation(location);
			if (this.cbCacheGeocode)
				this.cbCacheGeocode(location,place.Point.coordinates[1], place.Point.coordinates[0]);
			// Next
			setTimeout(function(){RQGMap.findNextLocation();}, 200);
		 }
	},
	
	/*
		Function : checkAllLocationsFound
	*/
	checkAllLocationsFound : function()
	{
		var nbFound = 0;
		for (var i=0;i<this.locations.length;i++)
			if (this.locations[i].found)
				nbFound++;	
		if (nbFound == this.locations.length)
		{
			if (this.__DEBUG__)
				console.log("nbFound =  "+nbFound);

			// Center around
			this.centerAroundLocations();
			
			// User callback
			if (this.cbAllPointsFound)
				this.cbAllPointsFound();
		}
	}

};
