Event.observe(window, 'load', initPage);

function initPage() {
	new SearchMap('MapSearch', 'rmMap', 
		{
			swLatField: 'MapSearch_MinimumLatitude',
			swLngField: 'MapSearch_MinimumLongitude',
			neLatField: 'MapSearch_MaximumLatitude',
			neLngField: 'MapSearch_MaximumLongitude',
			statusContainer: 'rmStatus'
		}
	);
}


var SearchMap = Class.create();
SearchMap.prototype = {
	initialize: function(form, container, options) {
		this.options = Object.extend({
			swLatField: null,
			swLngField: null,
			neLatField: null,
			neLngField: null,
			listingIcon: '/images/icons/silk/house_red.png',
			favoriteListingIcon: '/images/icons/silk/heart.png',
			hotListingIcon: '/images/icons/silk/house_green.png',
			statusContainer: null,
			searchingMsg: '<img src="/images/icons/silk/loading_big.gif" width="32" height="32" alt="" /> Searching for listings...',
			tooManyMarkersMsg: new Template('There are #{markerCount} listings available in this map region.  Zoom in or narrow your search parameters to see properties.'),
			loadingMsg: new Template('<img src="/images/icons/silk/loading_big.gif" width="32" height="32" alt="" /> Loading #{markerCount} listings...'),
			noResultsMsg: 'There are no listings available in this map region.  Zoom out or broaden your search parameters to see properties.',
			errorMsg: 'There was an unknown error.  Please try again.'
		}, options || {});
		
		this.form = $(form);
		if(this.form) {
			this.form.getElements().each(function(ele) {
				ele.observe('change', this.update.bindAsEventListener(this));
			}.bind(this));
		}
		this.container = $(container);
		this.status = $(this.options.statusContainer)
		this.mapBoundFields = {
			sw: {
				latitude: $(this.options.swLatField),
				longitude: $(this.options.swLngField)
			},
			ne: {
				latitude: $(this.options.neLatField),
				longitude: $(this.options.neLngField)
			}
		}
		this.markers = [];
		
		this.icon = new GIcon();
		//this.icon.shadow = "";
		this.icon.iconSize = new GSize(16, 16);
		this.icon.shadowSize = new GSize(16, 16);
		this.icon.iconAnchor = new GPoint(9, 10);
		this.icon.infoWindowAnchor = new GPoint(9, 7);
		
		if (GBrowserIsCompatible()) {
			
			Event.observe(window, 'beforeunload', function(e) {
			   GUnload();
			}); 			

			this.updateStatus('Initializing...');
			this.showStatus();
			
		  	with(this.mapBoundFields) {
				if(sw.latitude && sw.longitude && ne.latitude && ne.longitude) {
					this.bounds = new GLatLngBounds();
					
					this.bounds.extend(new GLatLng(parseFloat(sw.latitude.value), parseFloat(sw.longitude.value)));
					this.bounds.extend(new GLatLng(parseFloat(ne.latitude.value), parseFloat(ne.longitude.value)));
				}
			}
			this.gmap = new GMap2(this.container);
			this.gmap.addControl(new GLargeMapControl());
			this.gmap.addControl(new GMapTypeControl());
			
			var boxStyleOpts = {
				//opacity:.2,
				border:"2px solid red"
			}
			
			/* second set of options is for everything else */
			var otherOpts = {
				buttonHTML:'<img id="GMap_ZoomHandle" src="/images/icons/silk/shape_handles.png" width="16" height="16" alt="zoom" />',
				buttonZoomingHTML:'<img id="GMap_ZoomHandle" class="active" src="/images/icons/silk/shape_handles.png" width="16" height="16" alt="drag a box" />',
				buttonStartingStyle:{width:'25px', height:'23px'},
				buttonZoomingStyle: {width:'25px', height:'23px'}

			};
			
			/* third set of options specifies callbacks */
			var status = $('rmStatus')
			var callbacks = {
				buttonclick:function(){
					if(status)
						status.hide();
				},
				dragstart:function(){},
				dragging:function(x1,y1,x2,y2){},
				dragend:function(nw,ne,se,sw,nwpx,nepx,sepx,swpx){
					if(status)
						status.show();
					this.update();
				}.bind(this)
			};
			this.gmap.addControl(new DragZoomControl(boxStyleOpts, otherOpts, callbacks),new GControlPosition(G_ANCHOR_TOP_RIGHT,new GSize(5,30)));
			
			this.gmap.setCenter(this.bounds.getCenter(), this.gmap.getBoundsZoomLevel(this.bounds));

			GEvent.addListener(this.gmap, "dragend", function(){
			
				this.update();
		
			}.bindAsEventListener(this));
		
			GEvent.addListener(this.gmap, "zoomend", function(){
		
				this.update();
		
			}.bindAsEventListener(this));
			
			this.update();

		}
	},
	bounds: new GLatLngBounds(),
	icons: {
		listing: '/images/icons/silk/house.png',
		hotlisting: '/images/icons/silk/asterisk_orange.png',
		favoritelisting: '/images/icons/silk/heart.png'
	},
	fields: {},
	showStatus: function() {
		if(this.status)
			this.status.show();
	},
	hideStatus: function() {
		if(this.status)
			this.status.hide();
	},
	updateStatus: function(message) {
		if(this.status)
			this.status.update('<p>' + (message || '') + '</p>');
	},
	update: function() {
		this.gmap.clearOverlays(); 	
	
		this.updateStatus(this.options.searchingMsg)
		this.showStatus();
	
		var mapBoundsNE = this.gmap.getBounds().getNorthEast();
		var mapBoundsSW = this.gmap.getBounds().getSouthWest();
	
		this.mapBoundFields.ne.latitude.value = mapBoundsNE.lat()
		this.mapBoundFields.ne.longitude.value = mapBoundsNE.lng()
	
		this.mapBoundFields.sw.latitude.value = mapBoundsSW.lat()
		this.mapBoundFields.sw.longitude.value = mapBoundsSW.lng()
	

		
		var options = {
			method: 'post',
			parameters: {
				'Action': 'CountMarkers'
			},
			onFailure: function(transport) {
				this.updateStatus(this.options.errorMsg);
				this.showStatus();
			}.bind(this),
			onSuccess: function(transport, json) {
				var markerCount = json.markerCount;
				
				
				if(markerCount == 0)
					this.updateStatus(this.options.noResultsMsg);
				else if(markerCount > 100)
					this.updateStatus(this.options.tooManyMarkersMsg.evaluate({markerCount: markerCount}));
				else {
					this.updateStatus(this.options.loadingMsg.evaluate({markerCount: markerCount}));
					var options=  {
						parameters: {
							Action: 'GetMarkers'
						},
						onFailure: function(transport) {
							this.updateStatus(this.options.errorMsg);
							this.showStatus();
						}.bind(this),
						onSuccess: function(transport) {
							this.hideStatus();
							
							// JRM 10/18/08		
							// since IE doesn't like to run the eval statement below
							// strip the first 72 chars (the response header) from the response
							var list = transport.responseText;
							list = list.slice(72);							
							
							//and then call eval to build the arrays.
							var myData = eval("("+list+")");
							
						
							this.createMarkers(myData.listings);
							//this.createMarkers(transport.responseText.evalJSON().listings); - original code 10/18/08 JRM
							this.updateStatus("There are "+markerCount+" listings in this view.");
							this.showStatus();
						}.bind(this),
					
						
						onlyLatestOfClass: 'gmaps'
					}
					
					this.form.request(options);
				}
			}.bind(this),
			onlyLatestOfClass: 'gmaps'
		}
		this.form.request(options);
	},
	createMarkers: function(listings) {
		
		this.markers = [];
		var booleanItemHtml = new Template('<li class="#{className}"><span class="data">#{data}</span></li>');
		var detailItemHtml = new Template('<li class="#{className}"><span class="label">#{label}</span> <span class="data">#{data}</span></li>');
		//var mgrOptions = { borderPadding: 50, maxZoom: 15, trackMarkers: true };
		//var mgr = new MarkerManager(map, mgrOptions);

                //alert(listings.length);
		listings.each(function(listing, i) {
			var icon = new GIcon(this.icon);
			icon.image = (listing.isnew || listing.isreduced) ? this.options.hotListingIcon : (listing.isfavorite) ? this.options.favoriteListingIcon : this.options.listingIcon;
			
			var marker = new GMarker(
				new GLatLng(listing.latitude, listing.longitude),
				{	
					"icon": icon, 
					"title": this.helpers.toCurrencyString.call(this,listing.listprice)
						+ (listing.isnew ? ' : NEW' : '')
						+ (listing.isreduced ? ' : REDUCED' : '')
				}
			);	
	
			this.markers[i] = marker;
			var details = []
			
			Object.extend(
				listing,
				{
					address: $A([$A([listing.streetnumber, listing.streetname]).compact().join(' '), $A([listing.city, listing.state, listing.zip]).compact().join(', ')]).compact().join('<br />')

				}
			);
			var fields = [
				{name: 'listprice', format: this.helpers.toCurrencyString},
				{name: 'address'},
				{name: 'bedrooms', label: 'Beds:', format: this.helpers.toNumberString},
				{name: 'bathrooms', label: 'Baths:', format: this.helpers.toNumberString},
				{name: 'squarefeet', label: 'Sqf:', format: this.helpers.toNumberString},
				{name: 'acres', label: 'Acres:', format: this.helpers.toNumberString},
				{name: 'mlsid', label: 'MLS #:'}
			]
			if(listing.isnew) details.push(booleanItemHtml.evaluate({className: 'important', data: 'Just Added'}));
			if(listing.isreduced) details.push(booleanItemHtml.evaluate({className: 'important', data: 'Recently Reduced'}));
			
			fields.each(function(f) {
				if(listing[f.name])
					details.push(detailItemHtml.evaluate({className: f.name, label: f.label, data: (f.format ? f.format.call(this, listing[f.name]) : listing[f.name])}));
			}.bind(this));
			
			
			var moreInfoLinkTemplate = new Template('<a class="#{className}" href="/property/view.asp?MLSID=' + listing.mlsid + '" target="_blank">#{contents}</a>')
			var tabPageTemplate = new Template('<div class="tabpage" style="width: 280px; height: 160px; overflow: auto;">#{contents}</div>')
			var imageHtml = listing.photoid ? moreInfoLinkTemplate.evaluate({className: 'photolink', contents: '<img class="photo" src="http://fs.realfocus.com/getthumbnail.aspx?t=l&w=100&bs=0&id=' + listing.photoid + '" width="100" alt="Photo" />'}) : '';
			
			
			var detailHtml = imageHtml + ((details.length == 0) ? '' : '<ul class="details">' + details.join('') + '</ul>')
			
			+ '<ul class="actions"><li>' + moreInfoLinkTemplate.evaluate({contents: 'more info'}) + '</li><li><a class="zoomlink" href="#">zoom to</a></li><!--<li><a href="#">save</a></li>--></ul>';
			var moreHtml = ('<p>' + listing.remarks + '</p>') || null;
			var map = this.gmap;
			
			
			// add marker
			this.gmap.addOverlay(marker);
			
		

			//mgr.addMarker(marker,layer["zoom"],[0]);
			//mgr.refresh();
					
			GEvent.addListener(marker, 'click', function() {
				var labels = []
				var tabpages = []
				labels[0] = 'Details'
				tabpages[0] = tabPageTemplate.evaluate({contents: detailHtml});
				
				if(moreHtml) {
					labels[1] = 'More';
					tabpages[1] = tabPageTemplate.evaluate({contents: moreHtml});
				}
				
			  // adjust the width so that the info window is large enough for this many tabs
			  if (tabpages.length > 2) {
				tabpages[0] = '<div style="width:'+tabpages.length*88+'px">' + tabpages[0] + '</div>';
			  }
			  //alert(i+': '+mhtmls[0]);
			  var tabs = [];
			  for (var j=0; j<tabpages.length; j++) {
				tabs.push(new GInfoWindowTab(labels[j],tabpages[j]));
			  }
			  //alert(tabs);
			  marker.openInfoWindowTabsHtml(tabs,{maxWidth:200});

			  $$('a.zoomlink').invoke('observe','click',function(evt) {Event.stop(evt); map.setCenter(new GLatLng(listing.latitude, listing.longitude), (map.getZoom()+3 <= 17) ? map.getZoom()+3 : 17); marker.openInfoWindowTabsHtml(tabs)});
			});


			//mgr.addMarkers(this.markers,

		}.bind(this));
	},
	helpers: {
		
		toCurrencyString: function(num) {
			
			
			return '$' + this.helpers._formatNumber(num, 0, true, true, true);
		},
		toNumberString: function(num) {
			return this.helpers._formatNumber(num, 0, true, true, true);
		},
		_formatNumber: function(num,decimalNum,bolLeadingZero,bolParens,bolCommas) {
			if (isNaN(parseInt(num))) return "NaN";

			var tmpNum = num;
			var iSign = num < 0 ? -1 : 1;		// Get sign of number
			
			// Adjust number so only the specified number of numbers after
			// the decimal point are shown.
			tmpNum *= Math.pow(10,decimalNum);
			tmpNum = Math.round(Math.abs(tmpNum))
			tmpNum /= Math.pow(10,decimalNum);
			tmpNum *= iSign;					// Readjust for sign
			
			
			// Create a string object to do our formatting on
			var tmpNumStr = new String(tmpNum);
		
			// See if we need to strip out the leading zero or not.
			if (!bolLeadingZero && num < 1 && num > -1 && num != 0)
				if (num > 0)
					tmpNumStr = tmpNumStr.substring(1,tmpNumStr.length);
				else
					tmpNumStr = "-" + tmpNumStr.substring(2,tmpNumStr.length);
				
			// See if we need to put in the commas
			if (bolCommas && (num >= 1000 || num <= -1000)) {
				var iStart = tmpNumStr.indexOf(".");
				if (iStart < 0)
					iStart = tmpNumStr.length;
		
				iStart -= 3;
				while (iStart >= 1) {
					tmpNumStr = tmpNumStr.substring(0,iStart) + "," + tmpNumStr.substring(iStart,tmpNumStr.length)
					iStart -= 3;
				}		
			}
		
			// See if we need to use parenthesis
			if (bolParens && num < 0)
				tmpNumStr = "(" + tmpNumStr.substring(1,tmpNumStr.length) + ")";
		
			return tmpNumStr;		// Return our formatted string!
		}
	}


	
}







	/*
	Event.observe(window, 'load', initGMap);
	var Fields;
	var Status;
	var Icons;
	var map;
	var baseIcon;
	var gmarkers = [];

	function initGMap() {
		Icons = {
			listing: '/images/icons/silk/house.png',
			hotlisting: '/images/icons/silk/asterisk_orange.png',
			favoritelisting: '/images/icons/silk/heart.png'
		}
		
		Fields = {
			form: $('MapSearch'),
			sw: {
				latitude: $('MapSearch_MinimumLatitude'),
				longitude: $('MapSearch_MinimumLongitude')
			},
			ne: {
				latitude: $('MapSearch_MaximumLatitude'),
				longitude: $('MapSearch_MaximumLongitude')
			}
		}
		
		Status = {
			container: $('rmStatus'),
			update: function(message) {this.container.down('p').update(message)},
			show: function() {this.container.show()},
			hide: function() {this.container.hide()},
			messages: {
				searchingForMarkers: '<img src="/images/icons/silk/loading_big.gif" width="32" height="32" alt="" /> Searching for listings...',
				tooManyMarkers: new Template('There are #{markerCount} listings available in this map region.  Zoom in or narrow your search parameters to see properties.'),
				loadingMarkers: new Template('<img src="/images/icons/silk/loading_big.gif" width="32" height="32" alt="" /> Loading #{markerCount} listings...'),
				noMarkers: 'There are no listings available in this map region.  Zoom out or broaden your search parameters to see properties.',
				ajaxError: 'There was an unknown error.  Please try again.'
			}
		}
		
		baseIcon = new GIcon();
		baseIcon.shadow = "";
		baseIcon.iconSize = new GSize(16, 16);
		baseIcon.shadowSize = new GSize(16, 16);
		baseIcon.iconAnchor = new GPoint(9, 10);
		baseIcon.infoWindowAnchor = new GPoint(9, 7);

		
		var mapContainer = $('rmMap');
		
		//alert(GBrowserIsCompatible())
		if (GBrowserIsCompatible() && mapContainer) {
			
			Status.show();
		  
			var formMinLat = Fields.sw.latitude;
			var formMinLng = Fields.sw.longitude;
			var formMaxLat = Fields.ne.latitude;
			var formMaxLng = Fields.ne.longitude;
			

			var formBounds = new GLatLngBounds();
			
			formBounds.extend(new GLatLng(parseFloat(formMinLat.value), parseFloat(formMinLng.value)));
			formBounds.extend(new GLatLng(parseFloat(formMaxLat.value), parseFloat(formMaxLng.value)));
			
			map = new GMap2(mapContainer);
			map.addControl(new GLargeMapControl());
			
			var boxStyleOpts = {
				//opacity:.2,
				border:"2px solid red"
			}
			
			// second set of options is for everything else
			var otherOpts = {
				buttonHTML:'<img id="GMap_ZoomHandle" src="/images/icons/silk/shape_handles.png" width="16" height="16" alt="zoom" />',
				buttonZoomingHTML:'<img id="GMap_ZoomHandle" class="active" src="/images/icons/silk/shape_handles.png" width="16" height="16" alt="drag a box" />',
				buttonStartingStyle:null,
				buttonZoomingStyle: null
			};
			
			//third set of options specifies callbacks
			var callbacks = {
				buttonclick:function(){},
				dragstart:function(){},
				dragging:function(x1,y1,x2,y2){},
				dragend:function(nw,ne,se,sw,nwpx,nepx,sepx,swpx){
					updateMap();
				}
			};
			map.addControl(new DragZoomControl(boxStyleOpts, otherOpts, callbacks),new GControlPosition(G_ANCHOR_TOP_RIGHT,new GSize(10,10)));
			
			map.setCenter(formBounds.getCenter(), map.getBoundsZoomLevel(formBounds));

			GEvent.addListener(map, "dragend", function(){
			
				updateMap();
		
			});
		
			GEvent.addListener(map, "zoomend", function(){
		
				updateMap();
		
			});
			
			updateMap();

		}
	}


function updateMap() {
	map.clearOverlays(); 	

	Status.update(Status.messages.searchingForMarkers)
	Status.show();

	var mapBoundsNE = map.getBounds().getNorthEast();
	var mapBoundsSW = map.getBounds().getSouthWest();

	Fields.ne.latitude.value = mapBoundsNE.lat()
	Fields.ne.longitude.value = mapBoundsNE.lng()

	Fields.sw.latitude.value = mapBoundsSW.lat()
	Fields.sw.longitude.value = mapBoundsSW.lng()
	

	var options = {
		method: 'post',
		parameters: {
			'Action': 'CountMarkers'
		},
		onFailure: function(transport) {
			Status.update(Status.messages.ajaxError);
			Status.show();
		},
		onSuccess: function(transport, json) {
			var markerCount = json.markerCount;
			
			if(markerCount == 0)
				Status.update(Status.messages.noMarkers);
			else if(markerCount > 100)
				Status.update(Status.messages.tooManyMarkers.evaluate({markerCount: markerCount}));
			else {
				Status.update(Status.messages.loadingMarkers.evaluate({markerCount: markerCount}));
				var options = {
					parameters: {
						Action: 'GetMarkers'
					},
					onFailure: function(transport) {
						Status.update(Status.messages.ajaxError);
						Status.show();
					},
					onSuccess: function(transport) {
						Status.hide();
						createMarkers(transport.responseText.evalJSON().listings);
					},
					onlyLatestOfClass: 'gmaps'
				}
				
				Fields.form.request(options);
			}
		},
		onlyLatestOfClass: 'gmaps'
	}
	Fields.form.request(options);
}

function createMarkers(listings) {
	
	gmarkers = [];
	
	var detailItemHtml = new Template('<li class="#{className}"><span class="label">#{label}</span> #{data}</li>');

	listings.each(function(listing, i) {
		var icon = new GIcon(baseIcon);
		icon.image = Icons.listing;
		
		gmarkers[i] = new GMarker(
			new GLatLng(listing.latitude, listing.longitude),
			{icon: icon, title: listings.mlsid}
		);	

		marker = gmarkers[i];
		var details = []
		
		if(listing.listprice) details.push(detailItemHtml.evaluate({className: 'listprice', data: '$' + formatNumber(listing.listprice, 0, true, false, true)}));
		if(listing.bedrooms) details.push(detailItemHtml.evaluate({label: 'Beds:', data: listing.bedrooms}));
		if(listing.bathrooms) details.push(detailItemHtml.evaluate({label: 'Baths:', data: listing.bathrooms}));
		if(listing.squarefeet) details.push(detailItemHtml.evaluate({label: 'Sqf:', data: listing.squarefeet}));
		if(listing.mlsid) details.push(detailItemHtml.evaluate({label: 'MLS #:', data: listing.mlsid}));
		
		var moreInfoLinkTemplate = new Template('<a class="#{className}" href="/property/view.asp?MLSID=' + listing.mlsid + '" target="_blank">#{contents}</a>')
		var tabPageTemplate = new Template('<div class="tabpage" style="width: 250px; height: 140px; overflow: auto;">#{contents}</div>')
		var imageHtml = listing.photoid ? moreInfoLinkTemplate.evaluate({className: 'photolink', contents: '<img class="photo" src="http://fs.realfocus.com/getthumbnail.aspx?t=l&w=100&bs=0&id=' + listing.photoid + '" width="100" alt="Photo" />'}) : '';
		
		
		var detailHtml = imageHtml + ((details.length == 0) ? '' : '<ul class="details">' + details.join('') + '</ul>')
		
		+ '<ul class="actions"><li>' + moreInfoLinkTemplate.evaluate({contents: 'more info'}) + '</li></ul>';
		var moreHtml = ('<p>' + listing.remarks + '</p>') || null;
		
		GEvent.addListener(gmarkers[i], 'click', function() {
			var labels = []
			var tabpages = []
			labels[0] = 'Details'
			tabpages[0] = tabPageTemplate.evaluate({contents: detailHtml});
			
			if(moreHtml) {
				labels[1] = 'More';
				tabpages[1] = tabPageTemplate.evaluate({contents: moreHtml});
			}
			
		  // adjust the width so that the info window is large enough for this many tabs
		  if (tabpages.length > 2) {
			tabpages[0] = '<div style="width:'+tabpages.length*88+'px">' + tabpages[0] + '</div>';
		  }
		  //alert(i+': '+mhtmls[0]);
		  var tabs = [];
		  for (var j=0; j<tabpages.length; j++) {
			tabs.push(new GInfoWindowTab(labels[j],tabpages[j]));
		  }
		  //alert(tabs);
		  gmarkers[i].openInfoWindowTabsHtml(tabs);
		});
		
		// add marker
		map.addOverlay(marker);
				

	});
	
	
}
*/
function formatNumber()
/**********************************************************************
	IN:
		NUM - the number to format
		decimalNum - the number of decimal places to format the number to
		bolLeadingZero - true / false - display a leading zero for
										numbers between -1 and 1
		bolParens - true / false - use parenthesis around negative numbers
		bolCommas - put commas as number separators.
 
	RETVAL:
		The formatted number!
 **********************************************************************/
{ 
}

Ajax.currentRequests = {};

Ajax.Responders.register({
	onCreate: function(request) {
		if (request.options.onlyLatestOfClass && Ajax.currentRequests[request.options.onlyLatestOfClass]) {
			// if a request of this class is already in progress, attempt to abort it before launching this new request
			try { Ajax.currentRequests[request.options.onlyLatestOfClass].transport.abort(); } catch(e) {}
		}
		// keep note of this request object so we can cancel it if superceded
		Ajax.currentRequests[request.options.onlyLatestOfClass] = request;
	},
	onComplete: function(request) {
		if (request.options.onlyLatestOfClass) {
			// remove the request from our cache once completed so it can be garbage collected
			Ajax.currentRequests[request.options.onlyLatestOfClass] = null;
		}
	}
});
