(function() {

/**
 * @exports mxn.util.$m as $m
 */
var $m = mxn.util.$m;

/**
 * Initialise our provider. This function should only be called from within mapstraction code, not exposed as part
 * of the API.
 *
 * @private
 */
var init = function() {
	this.invoker.go('init', [ this.api ]);
};

/**
 * MapstractionGeocoder instantiates a geocoder with some API choice
 * @name mxn.MapstractionGeocoder
 * @constructor
 * @param {String} api The API to use
 * @param {Bool} debug optional parameter to turn on debug support - this uses alert panels for unsupported actions
 * @exports MapstractionGeocoder as mxn.MapstractionGeocoder
 */
var MapstractionGeocoder = mxn.MapstractionGeocoder = function(api, debug) {
	if (!api) {
		api = mxn.util.getAvailableProviders()[0];
	}

	/**
	 * The name of the active API.
	 * @name mxn.MapstractioGeocodern#api
	 * @type {String}
	 */
	this.api = api;

	this.geocoders = {};

	// set up our invoker for calling API methods
	this.invoker = new mxn.Invoker(this, 'MapstractionGeocoder', function() { return this.api; });

	init.apply(this);
};

mxn.addProxyMethods(MapstractionGeocoder, [
	/**
	 * Implements the geocoding process
	 */
	'geocode',

	/**
	 * Implements the reverse geocoding process
	 */
	'reverseGeocode',

	/**
	 * Implements the geocoding callback
	 */
	'geocodeCallback'

]);

/**
 * Change the Geocoding API to use
 *
 * @param {String} api The API to swap to
 */
MapstractionGeocoder.prototype.swap = function(api) {
	if (this.api == api) {
		return;
	}

	this.api = api;
	if (this.geocoders[this.api] == undefined) {
		init.apply(this);
	}
};

/**
 * Default Geocode error function
 */
MapstractionGeocoder.prototype.geocodeError = function(response) {
	alert("Sorry, we were unable to geocode that address");
};

})();
