(function(moduleName){

//-------------
// MAPSTRACTION
//-------------

	function addAPI(element, api) {
	    var me = this;
        if (GMap2) {
            if (GBrowserIsCompatible()) {
                this.maps[api] = new GMap2(element);

                GEvent.addListener(this.maps[api], 'click', function(marker,location) {
                    // If the user puts their own Google markers directly on the map
                    // then there is no location and this event should not fire.
                    if ( location ) {
                        me.clickHandler(location.y,location.x,location,me);
                    }
                });

                GEvent.addListener(this.maps[api], 'moveend', function() {
                    me.moveendHandler(me);
                });
                
                this.loaded[this.api] = true;
	            var loadHandlers = this.onload[this.api];
	            while(loadHandlers.length > 0){
		            var fn = loadHandlers.pop();
		            fn();
	            }
            }
            else {
                alert('browser not compatible with Google Maps');
            }
        }
        else {
            alert(api + ' map script not imported');
        }
	}
	
	function setCenterAndZoom(point, zoom) {
        var map = this.maps[this.api];
        map.setCenter(point.toGoogle(), zoom);
	}
	
	function getBounds() {
        var map = this.maps[this.api];
        var ne, sw, nw, se;
        var gbox = map.getBounds();
        sw = gbox.getSouthWest();
        ne = gbox.getNorthEast();
        return new mxn.BoundingBox(sw.lat(), sw.lng(), ne.lat(), ne.lng());
	}
	
	function addMarker(marker, old) {
	    var map = this.maps[this.api];
        var gpin = marker.toGoogle();
        marker.setChild(gpin);
        map.addOverlay(gpin);
        if (!old) {
            this.markers.push(marker);
        }
    }
    
    function addOverlay(url, autoCenterAndZoom) {
        var map = this.maps[this.api];
        var geoXML = new GGeoXml(url);
        map.addOverlay(geoXML, function() {
            if(autoCenterAndZoom) {
                geoXML.gotoDefaultViewport(map);
            }
        });
    }
    
//------------
// LATLONPOINT
//------------
    
    mxn.LatLonPoint.prototype.toGoogle = function() {
        return new GLatLng(this.lat,this.lon);
    };

//-------
// MARKER
//-------

    mxn.Marker.prototype.toGoogle = function() {
        var options = {};
        if(this.labelText){
            options.title =  this.labelText;
        }
        if(this.iconUrl){
            var icon = new GIcon(G_DEFAULT_ICON, this.iconUrl);
            icon.printImage = icon.mozPrintImage = icon.image;
            if(this.iconSize) {
                icon.iconSize = new GSize(this.iconSize[0], this.iconSize[1]);
                var anchor;
                if(this.iconAnchor) {
                    anchor = new GPoint(this.iconAnchor[0], this.iconAnchor[1]);
                }
                else {
                    // FIXME: hard-coding the anchor point
                    anchor = new GPoint(this.iconSize[0]/2, this.iconSize[1]/2);
                }
                icon.iconAnchor = anchor;
            }
            if(this.iconShadowUrl) {
                icon.shadow = this.iconShadowUrl;
                if(this.iconShadowSize) {
                    icon.shadowSize = new GSize(this.iconShadowSize[0], this.iconShadowSize[1]);
                }
            }
            options.icon = icon;
        }
        if(this.draggable){
            options.draggable = this.draggable;
        }
        var gmarker = new GMarker( this.location.toGoogle(),options);

        if(this.infoBubble){
            var theInfo = this.infoBubble;
            var event_action;
            if(this.hover) {
                event_action = "mouseover";
            }
            else {
                event_action = "click";
            }
            GEvent.addListener(gmarker, event_action, function() {
                gmarker.openInfoWindowHtml(theInfo, {
                    maxWidth: 100
                });
            });
        }

        if(this.hoverIconUrl){
            GEvent.addListener(gmarker, "mouseover", function() {
                gmarker.setImage(this.hoverIconUrl);
            });
            GEvent.addListener(gmarker, "mouseout", function() {
                gmarker.setImage(this.iconUrl);
            });
        }

        if(this.infoDiv){
            var theInfo = this.infoDiv;
            var div = this.div;
            var event_action;
            if(this.hover) {
                event_action = "mouseover";
            }
            else {
                event_action = "click";
            }
            GEvent.addListener(gmarker, event_action, function() {
                document.getElementById(div).innerHTML = theInfo;
            });
        }

        return gmarker;
    };
    
    // Register
	mxn.registerProvider(moduleName, {
		addAPI              : addAPI,
		setCenterAndZoom    : setCenterAndZoom,
		getBounds           : getBounds,
		addMarker           : addMarker,
		addOverlay          : addOverlay
	});

})('mapstraction.google');