(function($, module) {

//-------------
// MAPSTRACTION
//-------------

    // Module and provider requirements
    $.requireModules('boundingbox,utilities');
    $.requireProviders(module);

	$.Mapstraction = function(element, api, key, debug) {
        this.api = api; // could detect this from imported scripts?
        this.maps = {};
        this.currentElement = $.m(element);
        this.eventListeners = [];
        this.markers = [];
        this.layers = [];
        this.polylines = [];
        this.images = [];
        this.loaded = {};
        this.onload = {};

        // Mapstraction.writeInclude(api, "nothing");

        // optional debug support
        if (debug === true) {
            this.debug = true;
        }
        else {
            this.debug = false;
        }

        // This is so that it is easy to tell which revision of this file
        // has been copied into other projects.
        this.svn_revision_string = '$Revision: 208 $';
        this.addControlsArgs = {};

        // if (this.currentElement) {
        this.addAPI($.m(element), api, key);
    // }
	};
	
	$.Mapstraction.prototype.checkLoad = function(funcDetails){
	    if(this.loaded[this.api] === false) {
		    var scope = this;
		    this.onload[this.api].push( function() { funcDetails.callee.apply(scope, funcDetails); } );
		    return true;
	    }
	    return false;
    }

	$.Mapstraction.prototype.addAPI = function(element, api, key) {
   		this.loaded[api] = false;
        this.onload[api] = [];

        return $.invoke(this.api, module, 'addAPI', this, arguments);
	};
	
    $.Mapstraction.prototype.moveendHandler = function(me) {
        this.callEventListeners('moveend', {});
    };
    
    $.Mapstraction.prototype.callEventListeners = function(sEventType, oEventArgs) {
        oEventArgs.source = this;
        for(var i = 0; i < this.eventListeners.length; i++) {
            var evLi = this.eventListeners[i];
            if(evLi.event_type == sEventType) {
                // only two cases for this, click and move
                if(evLi.back_compat_mode) {
                    if(evLi.event_type == 'click') {
                        evLi.callback_function(oEventArgs.location);
                    }
                    else {
                        evLi.callback_function();
                    }
                }
                else {
                    var scope = evLi.callback_object || this;
                    evLi.callback_function.call(scope, oEventArgs);
                }
            }
        }
    };

	$.Mapstraction.prototype.setCenterAndZoom = function(point, zoom) {
	    if (this.checkLoad(arguments)) return;
        return $.invoke(this.api, module, 'setCenterAndZoom', this, arguments);
    };

    $.Mapstraction.prototype.getBounds = function() {
	    if (this.checkLoad(arguments)) return;
        return $.invoke(this.api, module, 'getBounds', this, arguments);
    };

	$.Mapstraction.prototype.addMarker = function(marker, old) {
       	if (this.checkLoad(arguments)) return;
        
        marker.mapstraction = this;
        marker.api = this.api;
        marker.location.api = this.api;
        marker.map = this.maps[this.api];
   
        return $.invoke(this.api, module, 'addMarker', this, arguments);
    };
    
    $.Mapstraction.prototype.addOverlay = function(url, autoCenterAndZoom) {
	    if (this.checkLoad(arguments)) return;
        if(autoCenterAndZoom == null) autoCenterAndZoom = false;
    };
	
    // Register
	$.registerModule(module);

})(mxn, 'mapstraction');