if (typeof(LaRoueVerte)=="undefined")
	LaRoueVerte={};


if (typeof(LaRoueVerte.GMap)=="undefined")
	LaRoueVerte.GMap = {};

/**
 * LaRoueVerte.GMap.Icon.* 
 * 
 * Use this module to manage google maps icons.
 */

LaRoueVerte.GMap.Icon = Class.create({
		initialize: function(options) {
			this.gIcon = null;
			this.options = options;
		},
		getIcon: function() {
			if (this.gIcon==null ) {
				this.gIcon = new GIcon();
				this.gIcon.image = this.getImagePath();
				
				if (this.options.color) {
					this.gIcon.iconSize = this.getIconSize();
					this.gIcon.shadowSize = this.getShadowSize();
					this.gIcon.iconAnchor = this.getIconAnchor();
					this.gIcon.infoWindowAnchor = this.getInfoWindowAnchor();
				} else {
					if (this.options.iconSize)
						this.gIcon.iconSize = this.getIconSize();
					if (this.options.shadowSize)
						this.gIcon.shadowSize = this.getShadowSize();
					if (this.options.iconAnchor)
						this.gIcon.iconAnchor = this.getIconAnchor();
					if (this.options.infoWindowAnchor)
						this.gIcon.infoWindowAnchor = this.getInfoWindowAnchor();
				}
			}
			return this.gIcon;
		},
		
		getMarker: function(markerOptions) {
			var defaultOptions = {
				title:this.options.title,
				icon:this.getIcon()
			};
			
			var markerSpecOptions;
			
			if (typeof(markerOptions)!='undefined') {
				markerSpecOptions = jQuery.extend( defaultOptions, markerOptions);
			} else {
				markerSpecOptions = defaultOptions;
			}
				
	        return new GMarker(this.getGLatLng(), markerSpecOptions);
		},
		
		getGLatLng: function() {
	        return new GLatLng(this.options.lat, this.options.lng);
		},
		
		getImagePath: function() {
			var imagePath;
			if (this.options.path) {
				imagePath = this.options.path;
			} else {
				var color;
				if (this.options.color) {
					color=this.options.color;
				} else {
					color = 'blue';
				}
				imagePath = '/common/img/mm_20_'+color+'.png';
			}
			
			var rootPath = this.options.rootPath?this.options.rootPath:LaRoueVerte.contextPath;
			
			return rootPath+imagePath;
		},
		
		getIconSize : function() {
			if (this.options.iconSize)
				return this.options.iconSize;
			else
				return new GSize(12, 20);
		},
		
		getShadowSize : function() {
			if (this.options.shadowSize)
				return this.options.shadowSize;
			else
				return new GSize(22, 20);
		},

		getIconAnchor: function() {
			if (this.options.iconAnchor)
				return this.options.iconAnchor;
			else
				return new GPoint(6, 20);
		},
		
		getInfoWindowAnchor: function() {
			if (this.options.infoWindowAnchor)
				return this.options.infoWindowAnchor;
			else
				return new GPoint(5, 1);
		},
		
		dummy: null
});

LaRoueVerte.GMap.Icon.IconFactory = (function() {
	
	var buildTcIcon = function(index) {
		var icon = new GIcon(G_DEFAULT_ICON);
		icon.image = LaRoueVerte.contextPath + "/common/img/markers/standard-numbered/marker" + index + ".png";
		return icon;
	};
	
	var buildCovIcon = function(latlng) {
		var lrvIcon = new LaRoueVerte.GMap.Icon({
			lat: latlng.lat(),
			lng: latlng.lng(),
			color: 'green'
		});
		return lrvIcon.getMarker();
	};
	
	var buildMapIcon = function(iconType, options) {
		
		var lastDash = iconType.lastIndexOf("-");
		var lastx = iconType.lastIndexOf("x");
		var imgWidth, imgHeight;
		if (lastDash == -1 || lastx == -1) {
			imgWidth = 32;
			imgHeight = 32;
		} else {
			imgWidth = iconType.substring(lastDash+1, lastx);
			imgHeight = iconType.substring(lastx+1, iconType.length);
		}

		var myOptions = jQuery.extend({
			iconSize: new GSize(imgWidth, imgHeight),
			shadowSize: new GSize(imgWidth, imgHeight),
			iconAnchor: new GPoint(imgWidth/2, imgHeight),
			infoWindowAnchor:new GPoint(imgWidth/2, imgHeight/2),
			rootPath: LaRoueVerte.contextPath,
			path: "/common/img/maps/" + iconType + ".png"
		}, options);
		
		return new LaRoueVerte.GMap.Icon(myOptions);
	};
	
	return {
		buildTcIcon: buildTcIcon,
		buildCovIcon: buildCovIcon,
		buildMapIcon: buildMapIcon
	}
})();

/**
 * LaRoueVerte.GMap.Icon.* 
 * 
 * Utils for google maps.
 */

LaRoueVerte.GMap.Utils = new Object();


/**
 * @return a Postgis point from the supplied Google LatLng
 */
LaRoueVerte.GMap.Utils.getPostgisFromGLatLng=function(gLatLng) {
	return "POINT("+gLatLng.lat()+" "+gLatLng.lng()+")";
}

/**
 * Modifies the map to show points and use gLatLngCenter as the center of the map
 */
LaRoueVerte.GMap.Utils.showPointsOnMapOnCenter=function(gLatLngList, gLatLngCenter, gmap, maxZoom) {
	var bounds = LaRoueVerte.GMap.Utils.getBounds(gLatLngList);
	
	var diffLatNE = Math.abs(bounds.getNorthEast().lat()-gLatLngCenter.lat());
	var diffLatSW = Math.abs(gLatLngCenter.lat()-bounds.getSouthWest().lat());

	var diffLngNE = Math.abs(bounds.getNorthEast().lng()-gLatLngCenter.lng());
	var diffLngSW = Math.abs(gLatLngCenter.lng()-bounds.getSouthWest().lng());

	var diffLat = Math.max(diffLatNE, diffLatSW);
	var diffLng = Math.max(diffLngNE, diffLngSW);

	 
	var nePt = new GLatLng(gLatLngCenter.lat()+diffLat, gLatLngCenter.lng()+diffLng);
	var swPt = new GLatLng(gLatLngCenter.lat()-diffLat, gLatLngCenter.lng()-diffLng);
	var newbounds = new GLatLngBounds(swPt, nePt);
	
	var zoom = gmap.getBoundsZoomLevel(newbounds);
	
	if (zoom>maxZoom)
		zoom = maxZoom;
	
	var center = newbounds.getCenter();
	
	gmap.setCenter(center, zoom);
}


/**
 * Modifies the map to show points
 */
LaRoueVerte.GMap.Utils.showPointsOnMap=function(gLatLngList, gmap, maxZoom) {
	var bounds = LaRoueVerte.GMap.Utils.getBounds(gLatLngList);
	
	var zoom = gmap.getBoundsZoomLevel(bounds);
	if (maxZoom && zoom > maxZoom)
		zoom = maxZoom;
	
	var center = bounds.getCenter();
	
	gmap.setCenter(center, zoom);
}

/**
 * Modifies the map to show points
 */
LaRoueVerte.GMap.Utils.getBounds=function(gLatLngList, gmap) {
	var minLat = gLatLngList[0].lat();
	var minLng = gLatLngList[0].lng();
	var maxLat = gLatLngList[0].lat();
	var maxLng = gLatLngList[0].lng();
	for ( var int = 1; int < gLatLngList.length; int++) {
		var gLatLng = gLatLngList[int];
		if (gLatLng.lat()<minLat)
			minLat = gLatLng.lat();
		if (gLatLng.lat()>maxLat)
			maxLat = gLatLng.lat();
		
		if (gLatLng.lng()<minLng)
			minLng = gLatLng.lng();
		if (gLatLng.lng()>maxLng)
			maxLng = gLatLng.lng();
		
	}
	
	minPt = new GLatLng(minLat, minLng);
	maxPt = new GLatLng(maxLat, maxLng);
	
	return new GLatLngBounds(minPt, maxPt);
}

/**
 */
LaRoueVerte.GMap.Utils.getPostgisPolygonStringFromBounds = function(gLatLngBounds) {
	//(NE.lat, SW.lng)                 ==>lng                 NE
	//          |
	//          \/
	//         lat
	// SW                                                  (SW.lat, NE.lng)
	//
	var polygon= "POLYGON((";
	polygon+=gLatLngBounds.getSouthWest().lat()+" "+gLatLngBounds.getSouthWest().lng();
	polygon+=","+gLatLngBounds.getNorthEast().lat()+" "+gLatLngBounds.getSouthWest().lng();
	polygon+=","+gLatLngBounds.getNorthEast().lat()+" "+gLatLngBounds.getNorthEast().lng();
	polygon+=","+gLatLngBounds.getSouthWest().lat()+" "+gLatLngBounds.getNorthEast().lng();
	polygon+=","+gLatLngBounds.getSouthWest().lat()+" "+gLatLngBounds.getSouthWest().lng();
	polygon+="))"
	return polygon;	
}

/**
 * Extracts a linestring POSTGIS formatted line string from the polyline 
 * @param polyline a GPolyLine object
 * @param distance on the polyline in meters
 */
LaRoueVerte.GMap.Utils.getPostgisLineStringFromPolyline=function(polyline,distance) {
	var itineraire = [];
	var nbreptsmax = Math.round((Math
			.round(distance / 1000)) / 40) + 5;
	if (nbreptsmax > 21)
		nbreptsmax = 21;
	var nmpoint = polyline.getVertexCount();
	var modulodist = Math.round(nmpoint / nbreptsmax);

	for (i = 0; i < nbreptsmax - 1; i++) {
		itineraire[i] = polyline.getVertex(Math.abs((i) * modulodist));
	}

	var concatiti = "LINESTRING(";
	for ( var i = 0; i < itineraire.length; i++) {
		var pts = itineraire[i];
		concatiti = concatiti + pts.lat() + " " + pts.lng() + ",";
	}
	concatiti = concatiti + polyline.getVertex(nmpoint - 1).lat() + " "
			+ polyline.getVertex(nmpoint - 1).lng();
	
	concatiti+=")";
	return concatiti;
}

/**
 * 
 */
LaRoueVerte.GMap.Utils.getAddress = function(num, rue, ville, codepostal, pays) {
	var address = "";
	if (num!=null && num !="") {
		address +=num;
	}
	if (rue!=null && rue !="") {
		address +=" "+rue+" , ";
	}
	if (ville!=null && ville !="") {
		if (codepostal!=null && codepostal !="") {
			address+=" "+codepostal+" ";
		}
		address +=ville+" , ";
	}
	address+=" , "+pays;
	return address;
}

/**
 * GeoCode address from details
 */
LaRoueVerte.GMap.Utils.geocodeFromAddressDetails=function(num, rue, ville, codepostal, pays, callback, errorCallback) {
	var address = LaRoueVerte.GMap.Utils.getAddress(num, rue, ville , codepostal, pays);
	LaRoueVerte.GMap.Utils.geocodeFromAddress(address, callback, errorCallback);
}

/**
 * GeoCode address from details
 */
LaRoueVerte.GMap.Utils.geocodeFromAddress=function(address, callback, errorCallback) {
	var geocoder = new GClientGeocoder();
	var geocodingCallback = function(res) {
		if (res==null)
			errorCallback("Error geocoding address:"+address, address);
		else
			callback(res);
	};
	geocoder.getLatLng(address,geocodingCallback);
}

LaRoueVerte.GMap.Utils.getLocations = function(address, onSuccess, onError) {
	var geocoder = new GClientGeocoder();
	var geocodingCallback = function(res) {
		if (res == null) {
			errorCallback("Error geocoding address:"+address, address);
		} else {
			callback(res);
		}
	};
	geocoder.getLocations(address,geocodingCallback);	
}

/**
 * Parses the given htmlDomContainer contents to retreive geo data written with
 * the "geo" microformat (see http://microformats.org/wiki/geo).
 * 
 * This method is compatible with the "map" function of jQuery.
 * 
 * Example of use:
 * 
 * collectGeoMicroformat(0, JQ("#container").get(0), function(container, from, to) { stuff here ... });
 * 
 * @param index
 * 			Index of the current element (only there to match jQuery's iterator format)
 * @param htmlDomContainer
 * 			An HTML dom node, containing a <div class="geo"></div> microformat.
 * @param data
 * 			Data to add to the parsed result. Can be either a value of a function
 * 			computing the data to set.
 * 			The computed LatLngs retreived from the microfomat are passed as well to
 * 			this function. (Example: function(container, from, to)).
 * 
 * @return
 * 			A structured object like below:
 * 			{
 * 				from: GLatLng,
 * 				to: GLatLng,
 * 				data: givendata (optional)
 * 			}
 */
LaRoueVerte.GMap.Utils.collectGeoMicroformat = function(index, htmlDomContainer, data) {
	
	// getting from and to geo microformats
	var jqContainer = JQ(htmlDomContainer);
	var	fromMF = jqContainer.find("div.geo.from"),
		toMF = jqContainer.find("div.geo.to");
	
	var fromLat = fromMF.children().get(0).innerHTML,
		fromLng = fromMF.children().get(1).innerHTML,
		toLat = toMF.children().get(0).innerHTML,
		toLng = toMF.children().get(1).innerHTML;
	
	var result = {
			from: new GLatLng(fromLat, fromLng),
			to:   new GLatLng(toLat, toLng)		
	}
	
	if (typeof(data) != "undefined") {
		if (typeof(data) == "function") {
			result.data = data(htmlDomContainer, result.from, result.to);
		} else {
			result.data = data;	
		}
	}
	return result;
}

/**
 * LaRoueVerte.GMap.* 
 * 
 * Objects / Classes to manipulate core gmap concepts
 */

/**
 * Loads custom JavaScript extensions.
 */
LaRoueVerte.GMap.loadCustomExtensions = function() {
	
	GMarker.prototype.setLRVData = function(data) {
		this.lrvData = data;
	}
	GMarker.prototype.setLastMarker = function(isLastMarker) {
		this.lastMarker = isLastMarker;
	}
	GMarker.prototype.isLastMarker = function() {
		return this.lastMarker;
	}
	GMarker.prototype.getLRVData = function() {
		return this.lrvData;
	}
	
	String.prototype.template = function (o) {
		if (typeof o == "undefined" || o == null) {
			return "";
		}
		return this.replace(/{([^{}]*)}/g,
				function (a, b) {
			var r = o[b];
			return typeof r === 'string' || typeof r === 'number' ? r : a;
		}
		);
	};
	
};

LaRoueVerte.GMap.Directions = Class.create({
	initialize: function(options) {
		if (options)
			this.options = options;
		else 
			this.options = {};
	},
	
	getLrvLineStringFromPoints: function(startPointLat, startPointLng, endPointLat, endPointLng, callback, errorCallback) {
		startPoint = new GLatLng(startPointLat, startPointLng);
		endPoint = new GLatLng(endPointLat, endPointLng);
		
		var gDirections;
		if (this.options.gmap)
			gDirections= new GDirections(this.options.gmap);
		else
			gDirections= new GDirections();
		
		gDirOptions = new Object();
		gDirOptions.travelMode = G_TRAVEL_MODE_DRIVING;
		gDirOptions.getPolyline = true;
		waypoints = new Array();
		waypoints.push(startPoint);
		waypoints.push(endPoint);
		
		GEvent.bind(gDirections, "load", this, function() { this.directionsLoaded(startPoint, endPoint, gDirections, callback)}.bind(this));
		if (errorCallback) {
			GEvent.bind(gDirections, "error", this, function() { this.directionsError(startPoint, endPoint, gDirections, errorCallback)}.bind(this));
		}
		gDirections.loadFromWaypoints(waypoints, gDirOptions);
	},
	
	getLrvLineStringFromAddressDetailsAndPoint: function(num, rue, ville, codepostal, pays, endPointLat, endPointLng, callback, errorCallback) {
		callbackGeoCoding = function(gLatLng) {
			this.getLrvLineStringFromPoints(gLatLng.lat(), gLatLng.lng(), endPointLat, endPointLng, callback, errorCallback);
		}.bind(this);
		
		LaRoueVerte.GMap.Utils.geocodeFromAddressDetails(num, rue, ville, codepostal, pays, callbackGeoCoding, errorCallback);
		
	},

	directionsLoaded: function(startPoint, endPoint,gDirections, callback) {
		lineString = LaRoueVerte.GMap.Utils.getPostgisLineStringFromPolyline(gDirections.getPolyline(), gDirections.getDistance().meters)
		callback(lineString, gDirections);
	},
	
	directionsError: function(startPoint, endPoint,gDirections, errorCallback) {
		errorCallback(gDirections.getStatus(), gDirections);
	},
	
	dummy: null
});

/**
 * LaRoueVerte.GMap.Tcs
 * 
 * Objects / Classes to TC concepts for a google map
 */

LaRoueVerte.GMap.Tcs = {};

LaRoueVerte.GMap.Tcs.Templates = {
	/**
	 * String template to display a TC path joinpoint. 
	 */
	INFO_WINDOW_TEMPLATE:
		"<div class=\"tc-infowindow\">\
		<img src=\"{image}\" />\
		<ul>\
		<li><strong>Départ :</strong> {departureTime} - {departureAddress}</li>\
		<li><strong>Arrivée :</strong> {arrivalTime} - {arrivalAddress}</li>\
		</ul>\
		</div>"	
};

/**
 * Controller for the given map:
 *  - Binds "click" handling on map markers for TC
 *  - Methods:
 *    - #initializeSectionsAndMarkers: Adds markers to the map 
 *      (the section objects are the same as returned by LaRoueVerte.GMap.Utils.collectGeoMicroformat)
 */
LaRoueVerte.GMap.Tcs.TcMapController = Class.create({
	initialize: function(map) {
		this.map = map;
		this.markers = [];
		this.lines = [];
		GEvent.bind(this.map, "click", this, this.onMapClick);
	},
	initializeSectionsAndMarkers: function(sections) {
		this.sections = sections;
		// iterating over sections to build GMarkers and polylines to display
		for (var i=0; i<this.sections.length; i++) {
			var section = this.sections[i];
			var marker = new GMarker(section.from, LaRoueVerte.GMap.Icon.IconFactory.buildTcIcon(i + 1));
			marker.setLRVData(section.data);
			var line = new GPolyline([section.from, section.to]);
			this.markers.push(marker);
			this.lines.push(line);
			this.map.addOverlay(marker);
			this.map.addOverlay(line);
		}
		// pushing last marker for arrival
		var lastMarker = new GMarker(this.sections[this.sections.length - 1].to);
		lastMarker.setLRVData(this.sections[this.sections.length - 1].data);
		lastMarker.setLastMarker(true);
		this.markers.push(lastMarker);
		this.map.addOverlay(lastMarker);
	},
	onMapClick: function(overlay, latlng, overlaylatlng) {
		if (overlay != null 
				&& overlay.getLRVData 
				&& !overlay.isLastMarker()
				&& overlay.getLRVData() != null) {
			this.map.openInfoWindowHtml(overlaylatlng, LaRoueVerte.GMap.Tcs.Templates.INFO_WINDOW_TEMPLATE.template(overlay.getLRVData()));
		}
	}
});

/**
 * LaRoueVerte.GMap.Cov
 * 
 * Objects / Classes to use covoiturage concepts within a google map
 */

LaRoueVerte.GMap.Cov = {};

LaRoueVerte.GMap.Cov.Constants = {
	COV_DEFAULT_ZOOM_LEVEL: 13
};

/**
 * Controlls covoitureurs on the given map.
 * Methods:
 *  - highlightCov: Hilights with a "ghost marker" the given covoiturage.
 *  - unhighlightCov: Unhiglights the given covoiturage.
 *  - pinCov: Pins the given covoiturage on the map and display the path
 *  - unpinCov: Unpins the given cov
 *  
 * Note: geodataContainer is an HTML container containing the geo microformat.
 * See LaRoueVerte.GMap.Utils.collectGeoMicroformat
 */
LaRoueVerte.GMap.Cov.CovController = Class.create({
	initialize: function(map) {
		this.map = map;
		// "ghost" markers to highlight covoiturage pathes
		this.covStart = null;
		this.covEnd = null;
		// false if ghost marker was never show. true otherwise.
		this.covLoadedOnce = false;
		// stored cov polylines
		this.covLines = [];
		this.covs = [];
	},
	highlightCov: function(geodataContainer) {
		// getting geo data
		var geodata = LaRoueVerte.GMap.Utils.collectGeoMicroformat(0, geodataContainer);
		if (!this.covLoadedOnce) {
			this.covLoadedOnce = true;
			// creating markers
			this.covStart = LaRoueVerte.GMap.Icon.IconFactory.buildCovIcon(geodata.from);
			this.covEnd = LaRoueVerte.GMap.Icon.IconFactory.buildCovIcon(geodata.to);
			this.map.addOverlay(this.covStart);
			this.map.addOverlay(this.covEnd);
		} else {
			this.covStart.setLatLng(geodata.from);
			this.covEnd.setLatLng(geodata.to);
			this.covStart.show();
			this.covEnd.show();
		}
	},
	unhighlightCov: function() {
		if (this.covStart && this.covEnd) {
			this.covStart.hide();
			this.covEnd.hide();
		}
	},
	pinCov: function(geodataContainer) {
		var geodata = LaRoueVerte.GMap.Utils.collectGeoMicroformat(0, geodataContainer);
		var pinCov = {
				covStart: LaRoueVerte.GMap.Icon.IconFactory.buildCovIcon(geodata.from),
				covEnd: LaRoueVerte.GMap.Icon.IconFactory.buildCovIcon(geodata.to)
		};
		this.map.addOverlay(pinCov.covStart);
		this.map.addOverlay(pinCov.covEnd);
		this.covs[geodataContainer.innerHTML] = pinCov;
		
		var tripGDir = new GDirections();
		GEvent.addListener(tripGDir, "load", function(){
			tripGDir.getPolyline().color='#FF00C9';
			this.map.addOverlay(tripGDir.getPolyline());
			this.covLines[geodataContainer.innerHTML] = tripGDir;
		}.bind(this));
		tripGDir.loadFromWaypoints([geodata.from, geodata.to],{getPolyline:true, preserveViewport: true});
	},
	unpinCov: function(geodataContainer) {
		var key = geodataContainer.innerHTML;
		if (this.covs[key] != null) {
			this.map.removeOverlay(this.covs[key].covStart);
			this.map.removeOverlay(this.covs[key].covEnd);
			var polyLine = this.covLines[key].getPolyline();
			if (polyLine != null) {
				this.map.removeOverlay(this.covLines[key].getPolyline());
			}
		
			this.covs[key] = null;
			this.covLines[key] = null;
		}
	},
	zoomCov: function(geodataContainer, pointType) {
		if (this.covs[geodataContainer.innerHTML] == null) {
			this.pinCov(geodataContainer);
		}
		var geodata = LaRoueVerte.GMap.Utils.collectGeoMicroformat(0, geodataContainer);
		this.map.setCenter(geodata[pointType], LaRoueVerte.GMap.Cov.Constants.COV_DEFAULT_ZOOM_LEVEL);
		this.map.showMapBlowup(geodata[pointType]);
	}
});

/**
 * LaRoueVerte.GMap.Helpers
 * 
 * Helpers to build google maps based on the same XHTML / JS source code.
 */

LaRoueVerte.GMap.Helpers = {};

/**
 * Controls a map to display both TCs and covoiturages markers, based
 * on common controllers CovController and TcMapController.
 */
LaRoueVerte.GMap.Helpers.TCAndCovMapController = Class.create({
	initialize: function(options) {
	
		this.options = JQ.extend({
			tcMicroformatDatasource: "#trip-details .first-cell",
			tcDataSourceDataFinder: this.findLRVDataInContainer,
			mapHolder: "#tc-covoitureurs-map"
		}, options);
		
		// min/max lat and lng to center map
		this.minLat = null;
		this.minLng = null;
		this.manLat = null;
		this.manLng = null;
							
		// getting points from TCs. Points are stored as latlng values
		// regarding the "geo" microformat contained in first-cell elements
		this.sections = JQ(this.options.tcMicroformatDatasource).map(function(index, element) {
			return LaRoueVerte.GMap.Utils.collectGeoMicroformat.apply(this, [index, element, this.fetchTcCustomData.bind(this)]);
		}.bind(this)).get();
		
		this.map = new GMap2(JQ(this.options.mapHolder).get(0));
		this.map.addControl(new GLargeMapControl());
	
		// adding cov generic controller
		this.covController = new LaRoueVerte.GMap.Cov.CovController(this.map);
		
		// adding TC generic controller
		this.tcsController = new LaRoueVerte.GMap.Tcs.TcMapController(this.map);
		
		// creating markers and lines from computed sections
		this.tcsController.initializeSectionsAndMarkers(this.sections);
		
		// centering map
		this.recenterAndZoomMap();
	},
	recenterAndZoomMap: function() {
		var sw = new GLatLng(this.minLat, this.minLng);
		var ne = new GLatLng(this.maxLat, this.maxLng);
		LaRoueVerte.GMap.Utils.showPointsOnMap([sw, ne], this.map);
	},
	fetchTcCustomData: function(container, from, to) {
		// setting min/max points to compute bounds
		this.setMinMaxField("Lat", from.lat());
		this.setMinMaxField("Lat", to.lat());
		this.setMinMaxField("Lng", from.lng());
		this.setMinMaxField("Lng", to.lng());
		
		return this.options.tcDataSourceDataFinder(container);
	},
	findLRVDataInContainer: function(container) {
		// getting custom LRV data
		var jqContainer = JQ(container);
		var row = jqContainer.parent();
		var cells = row.children(".full-mode");
		var img = jqContainer.children("img").get(0);
		return {
			departureAddress: cells.get(0).innerHTML,
			arrivalAddress: cells.get(1).innerHTML,
			departureTime: cells.get(2).innerHTML,
			arrivalTime: cells.get(3).innerHTML,
			image: img.src
		};
	},
	setMinMaxField: function(field, value) {
		if (this["min" + field] == null || this["min" + field] > value) {
			this["min" + field] = value;
		}
		if (this["max" + field] == null || this["max" + field] < value) {
			this["max" + field] = value;
		}
	},
	highlightCov: function(geodataContainer) {
		this.covController.highlightCov(geodataContainer);
	},
	unhighlightCov: function() {
		this.covController.unhighlightCov();
	},
	pinCov: function(geodataContainer) {
		this.covController.pinCov(geodataContainer);
	},
	unpinCov: function(geodataContainer) {
		this.covController.unpinCov(geodataContainer);
	},
	zoomCov: function(geodataContainer, pointType) {
		this.covController.zoomCov(geodataContainer, pointType);
	}
});


