function FMap(aDivID, aCenter) 
{
	this._divID = aDivID;
	this._googleMap = null;
	if(aCenter)
		this._center = aCenter;
	else 
		this._center = new FVector2(37.4419, -122.1419);
	
	// Default zoom value
	this._zoom = FConfig["DEFAULT_MAP_ZOOM"];
	
	this._callbackArray = new Array();
	this._markers = new Array();
	
	this._geocoder = new GClientGeocoder();
	this._loading = false;
}

// Private variables
FMap.prototype._divID;
FMap.prototype._googleMap;
FMap.prototype._center;
FMap.prototype._zoom;
FMap.prototype._callbackArray;
FMap.prototype._markers;
FMap.prototype._geocoder;
FMap.prototype._loading;

FMap.prototype._getGMap = function()
{
	return this._googleMap;
}

FMap.prototype.getBounds = function()
{
	var lTop = new FVector2(this._googleMap.getBounds().getSouthWest().lat(), this._googleMap.getBounds().getSouthWest().lng());
	var lBottom = new FVector2(this._googleMap.getBounds().getNorthEast().lat(), this._googleMap.getBounds().getNorthEast().lng());
	return new FRectangle(lTop, lBottom);
}

FMap.prototype.getMarker = function(contentId, type, callback)
{
	FMapService_getMarkerByContentIDAndType(contentId, type,
		function(result)
		{
			callback(FMarker.createFromArray(result));
		});
}

// Public functions
FMap.prototype.load = function() 
{
	if (GBrowserIsCompatible())
	{
		this._googleMap = new GMap2(document.getElementById(this._divID));
		this.setCenter(this._center);
		this._googleMap.disableDoubleClickZoom();
		// Setup listeners
		var _proxy = this;
		GEvent.addListener(this._googleMap, "click", function(overlay, latlng, overlaylatlng) { _proxy._clicked(overlay, latlng, overlaylatlng); });
		GEvent.addListener(this._googleMap, "moveend", function() { _proxy._endmove(); });
		GEvent.addListener(this._googleMap, "dragend", function() { _proxy._dragend(); });
	}
}

FMap.prototype.setMapType = function(aType)
{
	switch(aType)
	{
		case "default":
			this._googleMap.setMapType(this._googleMap.getMapTypes()[0]);
			break;
		case "satellite":
			this._googleMap.setMapType(this._googleMap.getMapTypes()[1]);
			break;
		case "hybrid":
			this._googleMap.setMapType(this._googleMap.getMapTypes()[2]);
			break;
	}
}


FMap.prototype.addMarker = function(aMarker) 
{

	if(this._googleMap)
	{
		this._googleMap.addOverlay(aMarker.getGMapMarker());
		this._googleMap.addOverlay(aMarker.getGMapMarker().tooltip);
		aMarker._initialize(this);
	}
	this._markers.push(aMarker);
}
FMap.prototype.removeMarker = function(aMarker)
{
	this._googleMap.removeOverlay(aMarker.getGMapMarker().tooltip);
	this._googleMap.removeOverlay(aMarker.getGMapMarker());
	aMarker._destroy();
}
FMap.prototype.clearMarkers = function(aMarker)
{
	for(i = 0; i < this._markers.length; i++)
		this.removeMarker(this._markers[i]);
	
	this._markers = new Array();
}
FMap.prototype.panTo = function(aCenter) { this._center = aCenter; this._googleMap.panTo(aCenter) };
FMap.prototype.setCenter = function(aCenter) { this._center = aCenter; this._updateMapView(); }
FMap.prototype.getCenter = function() { return this._center; }
FMap.prototype.setZoom = function(aZoom) { this._zoom = aZoom; this._updateMapView(); }
FMap.prototype.getZoom = function() { return this._zoom; }
FMap.prototype.addListener = function (aName, aCallback)
{
	if(this._callbackArray[aName])
	{
		this._callbackArray[aName][0]++;
		this._callbackArray[aName][this._callbackArray[aName][0]] = aCallback;
		return this._callbackArray[aName][0];
	} else
	{
		this._callbackArray[aName] = new Array();
		this._callbackArray[aName][0] = 1;
		this._callbackArray[aName][this._callbackArray[aName][0]] = aCallback;
		return this._callbackArray[aName][0];
	}
}
FMap.prototype.removeListener = function (aName, aHandle)
{
	if(aHandle == 0) return;
	if(this._callbackArray[aName])
	{
		this._callbackArray[aName][aHandle] = null;
	}
}

FMap.prototype.searchAddress = function(aSearchStr, aCallback)
{
		this._geocoder.getLatLng(
    		aSearchStr,
    		function(point) 
    		{
      			if (!point) 
      			{
        			aCallback(new FVector2(0, 0), false);
      			} else 
      			{
        			aCallback(new FVector2(point.y, point.x), true);
      			}
      		});
}
// EOF Public function

// Private functions
FMap.prototype._updateMapView = function() { if(this._googleMap) this._googleMap.setCenter(this._center.toGLang(), this._zoom); }

FMap.prototype._clicked = function(overlay, latlng, overlaylatlng)
{
	for(var lCallback in this._callbackArray["clicked"])
	{
		if(lCallback != 0 && this._callbackArray["clicked"][lCallback]) { this._callbackArray["clicked"][lCallback](new FVector2(latlng.lat(), latlng.lng())); }
	}
}

FMap.prototype._endmove = function()
{
	this._center.x = this._googleMap.getCenter().lat();
	this._center.y = this._googleMap.getCenter().lng();
	
	for(var lCallback in this._callbackArray["moveend"])
	{
		if(lCallback != 0 && this._callbackArray["moveend"][lCallback]) { this._callbackArray["moveend"][lCallback](this._center); }
	}
}
FMap.prototype._dragend = function()
{
	this._center.x = this._googleMap.getCenter().lat();
	this._center.y = this._googleMap.getCenter().lng();
	
	for(var lCallback in this._callbackArray["dragend"])
	{
		if(lCallback != 0 && this._callbackArray["dragend"][lCallback]) { this._callbackArray["dragend"][lCallback](this._center); }
	}
}
// EOF Private functions