var NRDCMap = Class.create();
Object.extend(NRDCMap.prototype, CustomGoogleMap.prototype);

fixWebKitInheritanceBug(NRDCMap);

NRDCMap.CONFIG = Object.clone(CustomGoogleMap.CONFIG);
NRDCMap.CONFIG['info_window_width'] = "300";
NRDCMap.CONFIG['info_window_markup_order'] = $w('title address img description phone url');
NRDCMap.CONFIG['info_window_templates'] = {
	'title'       : '<div class="Title">#{title}<\/div>',
	'address'     : '<div class="Address">#{address}<\/div>',
	'img'         : '<div class="Image"><img src="#{img}" class="Thumbnail" alt="#{title}" \/><\/div>',
	'description' : '<div class="Description">#{description}<\/div>',
	'phone'       : '<div class="Phone">#{phone}<\/div>',
	'url'         : '<div class="Website"><a href="#{url}">#{url}<\/a></div>'
};

NRDCMap.prototype.populateMapFromJSON = function(markers) {
	this.location_nodes = [];

	markers.each(function(marker){
		// create the marker using our data and add it to the map
		this.addMarkerToMap(this.createMarker(marker.attributes));
	}.bind(this));

  this.zoomToMarkers(this.CONFIG['zoom_slop_percentage']);
};

NRDCMap.prototype.handleMarkerClick = function(marker) {
	// remove the selected class on all the location markers
	this.location_nodes.each(function(node){
		node.removeClassName(this.CONFIG['selected_class']);
	}.bind(this));

	try {
		// activate the current location
		$(this.CONFIG['location_id_prefix'] + marker.data['id']).addClassName(this.CONFIG['selected_class']);
	} catch(e) { }

	// if a url is available for the info window contents, retrieve it
	if (!this.CONFIG['info_window_url'].blank()) {

		new Ajax.Request(this.CONFIG['info_window_url'] + marker.data.id + ".js", {
			'method' : 'get', 
			'onSuccess' : this.markerInfoWindowCallback.bind(this, marker),
			'onFailure' : Prototype.emptyFunction
		});

	// else use the data gathered during the DOM extraction
	} else {
		marker.openInfoWindowHtml(this.wrapInfoWindowHTML(marker, this.generateMarkerInfoWindowContent(marker)));
	}
};

Object.extend(NRDCMap.prototype, {

	getCenter: function() {
		return this.gmap.getCenter();
	},

	lat: function() {
		return this.getCenter().lat();
	},

	lng: function() {
		return this.getCenter().lng();
	},

	setZoom: function(level) {
		this.gmap.setZoom(level);
	},

	// Similar to Gmap2#pan2, but takes a hash argument instead of a GLatLng
	// instance.
	panTo: function(options) {
		var lat = options.lat || this.lat();
		var lng = options.lng || this.lng();

		// I can't find any condition that raises an error here.  Probably we
		// should test the validity of lat/lng and return false if they're not.
		try {
			this.gmap.panTo(new GLatLng(lat, lng));
			return true;
		} catch(e) {
			return false;
		}
	}
});

var MapForm = Class.create();

MapForm.CONFIG = {
	lat_input_name: "latitude",
	lng_input_name: "longitude",
	zoom_input_name: "zoom",
	map_controls: ['GLargeMapControl', 'GMapTypeControl'],
	map_default_zoom: 5,
	map_center_point_default: new GLatLng(0,0),
	map_center_point: new GLatLng(0,0)	
};

fixWebKitInheritanceBug(MapForm);

Object.extend(MapForm.prototype, {
	initialize: function(form_id, map_id, config) {
		this.CONFIG = Object.extend(Object.clone(this.constructor.CONFIG), config || {});

		var form = $(form_id);
		var map = new NRDCMap(map_id, null, { map_center_point_default: this.CONFIG['map_center_point'],
																					map_center_point: this.CONFIG['map_center_point'],
																					map_default_zoom: this.CONFIG['map_default_zoom'],
																					map_controls: this.CONFIG['map_controls'],
																					map_data_url: "http://localhost:3000/maps/1/addresses.js"
																					});
		window[map_id] = map;

		var lat_input = form[this.CONFIG.lat_input_name];
		var lng_input = form[this.CONFIG.lng_input_name];
		var zoom_input = form[this.CONFIG.zoom_input_name];

		// Register event handlers
		lat_input.observe('blur', this._handleLatBlur.bindAsEventListener(this, lat_input, map));
		lng_input.observe('blur', this._handleLngBlur.bindAsEventListener(this, lng_input, map));
		zoom_input.observe('blur', this._handleZoomBlur.bindAsEventListener(this, zoom_input, map));
	},

	_handleLatBlur: function(e, el, map) {
		map.panTo({lat: el.value});
	},

	_handleLngBlur: function(e, el, map) {
		map.panTo({lng: el.value});
	},

	_handeZoomBlur: function(e, el, map) {
		map.setZoom(level);
	}
});