
// ==============================================================================================
function BRMap() {
	this.debug = document.getElementById("debug");
	
	this.listRescueRequests = false;
	this.listProviders = false;
	
	this.createRequestFunction = undefined;
	this.onChangePointFunction = undefined;
	this.initLocationFunction = undefined;
	
	this.addrField = undefined;
	this.addressMsg = undefined;
	
	this.relMouseX = undefined;
	this.relMouseY = undefined;
	this.marker = undefined;
	this.prevCenter = undefined;
	this.prevLoadRadius = undefined;
	this.markers = undefined;
	this.myPoint = undefined;
	
	this.maxProviders = 100;
	
	this.size = undefined;
}
BRMap.prototype = {
	setSize : function (width, height) {
		this.size = new YSize(width, height);
		if ( this.map != undefined ) {
			this.map.resizeTo( this.size );
		}
	}
	,
	init : function(mapContainerId) {
		var thisObj = this;
		
		this.mapContainer = document.getElementById(mapContainerId);
	    this.map = new YMap(this.mapContainer, undefined, this.size); 
		this.map.addPanControl();
		this.map.addZoomLong();
		
		
		/**
		 * Tracks mouse movement
		 */
		this.mapContainer.onmousemove = function(e) {
		  if( !e ) {
		    if( window.event ) {
		      //Internet Explorer
		      e = window.event;
		    } else {
		      //total failure, we have no way of referencing the event
		      return;
		    }
		  }
		  if( typeof( e.pageX ) == 'number' ) {
			//most browsers
			var xcoord = e.pageX;
			var ycoord = e.pageY;
		  } else if( typeof( e.clientX ) == 'number' ) {
		    //Internet Explorer and older browsers
		    //other browsers provide this, but follow the pageX/Y branch
		    var xcoord = e.clientX;
		    var ycoord = e.clientY;
		    var badOldBrowser = ( window.navigator.userAgent.indexOf( 'Opera' ) + 1 ) ||
		     ( window.ScriptEngine && ScriptEngine().indexOf( 'InScript' ) + 1 ) ||
		     ( navigator.vendor == 'KDE' )
		    if( !badOldBrowser ) {
		      if( document.body && ( document.body.scrollLeft || document.body.scrollTop ) ) {
		        //IE 4, 5 & 6 (in non-standards compliant mode)
		        xcoord += document.body.scrollLeft;
		        ycoord += document.body.scrollTop;
		      } else if( document.documentElement && ( document.documentElement.scrollLeft || document.documentElement.scrollTop ) ) {
		        //IE 6 (in standards compliant mode)
		        xcoord += document.documentElement.scrollLeft;
		        ycoord += document.documentElement.scrollTop;
		      }
		    }
		  } else {
		    //total failure, we have no way of obtaining the mouse coordinates
		    return;
		  }
		  
			thisObj.relMouseX = xcoord - getOffsetX(this);
			thisObj.relMouseY = ycoord - getOffsetY(this);
		};
		
		YEvent.Capture( this.map, EventsList.MouseDoubleClick,	function (o) {thisObj.doubleClick(o);}, {} );
		YEvent.Capture( this.map, EventsList.onEndGeoCode,		function (o) {thisObj.geoCodeDone(o);}, {} );
		YEvent.Capture( this.map, EventsList.onPan,				function (o) {thisObj.onMapChange(o);}, {} );
		YEvent.Capture( this.map, EventsList.changeZoom,		function (o) {thisObj.onMapChange(o);}, {} );
	
		// We have to init it at a point otherwise if we refreshMarkers there will be "center" of the map so code will crash
		//var myPoint = new YGeoPoint(37.4041960114344,-122.008194923401);
		//map.drawZoomAndCenter(myPoint, 3);
		
		// Inits location
		if ( this.initLocationFunction != undefined ) {
			this.initLocationFunction();
		} else {
			// What do?? we need to default.
		}
	}
	,
	/**
	 * Markers will refresh when the passed in field change
	 */
	addRefreshMarkersOnChangeOfSelect : function(field) {
		var thisObj = this;
		field.onchange = function() {
			thisObj.refreshMarkers(true);
		}
	}
	,
	addRefreshMarkersOnChangeOfRadio : function(fieldList) {
		var thisObj = this;
		for (var i=0; i < fieldList.length; i++ ) {
			var field = fieldList[i];
			field.onclick = function() {
				thisObj.refreshMarkers(true);
			}
		}
	}
	,
	setupAddrField : function(field, addressMsg) {
		this.addrField = field;
		this.addressMsg = addressMsg;
		
		var thisObj = this;
		this.addrField.updateMap = function() {
			// Enter pushed. Update marker location, and make browse not submit form (by returning false).
			var address = thisObj.addrField.value;
			if ( address != "" ) {
				thisObj.changePointToAdddress(address);
			}
			
			this.value = "";
			this.curValue = "";
		}
		this.addrField.onkeypress = function (event) {
			if (window.event) event = window.event; // IE
			if (event.keyCode == 13) {
				this.updateMap();
				return false;
			} else {
				return true;
			}
		}
		this.addrField.onfocus = function () {
			this.curValue = this.value;
			this.select();
		}
		this.addrField.onblur = function () {
			this.checkForChange();
		}
		this.addrField.checkForChange = function () {
			var r = false;
			if ( this.curValue != this.value && this.value != "" ) {
				// Value changed
				if ( confirm("Would you like to move the marker to '"+this.value+"'?") ) {
					this.updateMap();
					r = true;
				} else {
					this.value = "";
				}
			}
			return r;
		}
	}
	,
	/**
	 * Changes the marker to the point specified
	 */
	changePointTo : function(point, zoom) {
		//if ( zoom == undefined ) zoom = 3;
		
		this.myPoint = point;
		
		// Update lat and lon fields
		if ( this.onChangePointFunction != undefined ) {
			this.onChangePointFunction(this.myPoint.Lat, this.myPoint.Lon);
		}
		
		// Create a marker positioned at a lat/lon
		if ( this.marker != undefined ) {
			this.map.removeOverlay(this.marker);
		}
		var img = new YImage(baseHref + "images/icons/map-x.png", new YSize(30, 30), new YCoordPoint(0,0), new YCoordPoint(-15,15));
		this.marker = new YMarker(this.myPoint, img);
		//this.marker.addLabel("Your location");
		//marker.addAutoExpand("<div style='width: 100px; height: 100px; color: blue;'>hello</div>");
		this.map.addOverlay(this.marker);
		
		
		if ( zoom == undefined ) {
// 			This seemed to some how screw up the centering of the map... we can't do this.. looks like they might do it anways.
//			this.map.panToLatLon( this.myPoint );
		} else {
			this.map.drawZoomAndCenter(this.myPoint, zoom);
		}
		
		//if ( this.map.getCenterLatLon() == undefined ) {
		//	this.map.drawZoomAndCenter(this.myPoint, zoom);
		//} else {
		//	this.map.panToLatLon( this.myPoint );
		//	this.map.setZoomLevel( zoom );
		//}
		
		// Need to refresh markers
		this.refreshMarkers();
	}
	,
	
	/**
	 * Moves the marker the specifies where they are to the location they just double clicked
	 */
	doubleClick : function(arg) {
		this.changePointTo(this.map.convertXYLatLon( new YCoordPoint(this.relMouseX, this.relMouseY) ));
		// Clear message out. Clear address too
		this.changeAddressMsg("");
		if ( this.addrField != undefined )
			this.addrField.value = "";
	}
	,
	changeAddressMsg : function(text) {
		if ( this.addressMsg != undefined ) {
			while (this.addressMsg.hasChildNodes()) {
				this.addressMsg.removeChild(this.addressMsg.firstChild);
			}
			this.addressMsg.appendChild( document.createTextNode(text) );
		}
	}
	,
	/**
	 * Changes the marker to the address specified
	 */
	changePointToAdddress : function(address) {
		this.map.geoCodeAddress( address );
	}
	,
	geoCodeDone : function(result) {
		var map = result.ThisMap;
		if ( result.success == 0 ) {
			this.changeAddressMsg("Unable to find the address specified: "+result.Address);
		} else {
			var zoom = map.getZoomLevel();
			if ( zoom > 10 ) zoom = 6;
			this.changePointTo( result.GeoPoint, zoom );
			this.changeAddressMsg("");
		}
	}
	,
	/**
	 * Wathces the map for movement in order to request new markers from the server.
	 */
	onMapChange : function() {
		// Gets called when user pans
		this.refreshMarkers();
	}
	,
	refreshMarkers : function(forceRefresh) {
		if ( forceRefresh == undefined ) forceRefresh = false;
		
		var center = this.map.getCenterLatLon();
		var zoomLevel = this.map.getZoomLevel();
		var milesPerPixel = this.map.getUnitsPerPixel(zoomLevel).miles
		var greatestToEdgePixels = this.map.getOuterRadius();
		var greatestMilesToEdge = milesPerPixel * greatestToEdgePixels;
	
		if ( greatestMilesToEdge > 150 && this.listProviders ) {
			// Radius to wide AND showing providers. We don't load any!
			// NOTE if only showing rescue requests we always query the server
			this.clearMarkers();
			this.prevCenter = undefined;
			this.prevLoadRadius = undefined;
		} else {
			// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
			// Determines if we need to update
			var load = true;
			if ( !this.listRescueRequests && !this.listProviders ) {
				// If not loading rescue requests nor providers we don't have to do anything
				load = false;
			} if ( !forceRefresh && this.prevCenter != undefined ) {
				// Determines if we need to load. Doesn't check if its forcing a refresh
				var dist = center.distance(this.prevCenter).miles;
				
				var howClose = (this.prevLoadRadius - dist);	// How many miles we are to where we don't have dta
				
				//this.debug.append("howClose: " + howClose + "  greatestMilesToEdge: "+greatestMilesToEdge+"<br/>");
				
				// If we can NOT see more than what is loaded then we dont have to load again
				if ( greatestMilesToEdge < howClose  ) {
					load = false;
				}
			}

			// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
			// Loads markers if needed
			if ( load ) {
				this.prevCenter = center;
				// Loads extra so the user can pan without it having to load moer
				this.prevLoadRadius = greatestMilesToEdge * 1.2;
				
				//this.debug.append("Loading.. this.prevLoadRadius: "+ this.prevLoadRadius+"<br/>");
				
				var myConn = new XHConn();
				if (!myConn) alert("Error creating connection.");
				
				// Convert action to POST data
				var postDataArray = new Array();
				if ( this.listRescueRequests ) {
					postDataArray[postDataArray.length] = "listRescueRequests=true";
				}
				if ( this.listProviders ) {
					postDataArray[postDataArray.length] = "listProviders=true";
				}
				postDataArray[postDataArray.length] = "radiusInMiles="+this.prevLoadRadius;
				postDataArray[postDataArray.length] = "latitude="+center.Lat;
				postDataArray[postDataArray.length] = "longitude="+center.Lon;
				
				postDataArray[postDataArray.length] = "maxProviders="+this.maxProviders;
				
				if ( this.createRequestFunction != undefined ) {
					this.createRequestFunction( postDataArray );
				}

				var postData = postDataArray.join("&");
				var thisObj = this;
				
				//this.changeAddressMsg(postData);
				
				myConn.connect(baseHref+'remote/list.xml', 'POST', postData,
						function (oXML) {
							var responseDoc = oXML.responseXML;
			
							thisObj.changeAddressMsg("");
							
							if ( responseDoc == null ) {
								// If the user stops it some how in the middle of the request.. eg submits a form taht leaves the page, this happens.
								// That is why we removed the alert.
								//alert("ERROR!. Problem with response from server: \n\n" + oXML.responseText);
							} else {
								// Parse response
								var root = responseDoc.documentElement;
							
								if ( root.nodeName == "error" ) {
									alert("Error: " + root.nodeValue);
								}
								
								// Remove current markers
								thisObj.clearMarkers();

								// Cycle through providers
								var children = root.childNodes;
								for ( var i=0; i < children.length; i++ ) {
									var node = children.item(i);
									
									var obj = {};
									
									if ( node.nodeName == "error" ) {
										var errorName = node.getAttribute("name");
										if ( errorName == "exceeds-max-results" )  {
											// There are more.
											thisObj.changeAddressMsg("Displaying only the first " + thisObj.maxProviders + " providers near the X marker.");
										} else {
											// Unknown error
											alert("Error: " + node.nodeValue);
										}
									} else if (node.nodeName == "p") {
										// Provider
										// NOTE: <p../> is used instead of <provider../> to cut down on bandwidth
										
										obj.id			= node.getAttribute("id");
										obj.display		= node.getAttribute("d");	// "d" means "display"
										obj.lat			= node.getAttribute("lat");
										obj.lon			= node.getAttribute("lon");
										
										obj.towing		= node.getAttribute("st") == "true";
										obj.bus			= node.getAttribute("sb") == "true";
										obj.mr			= node.getAttribute("sm") == "true";
										
										// ===================
										
										var img = new YImage();
										img.size = new YSize(24,24);
										img.offset = new YCoordPoint(-12,12);
										img.offsetSmartWindow = new YCoordPoint(12, 12);
										
										if ( obj.bus == true ) {
											img.src = baseHref + "images/icons/bus.png";
										} else if ( obj.towing == true ) {
											img.src = baseHref + "images/icons/tow.png";
										} else {
											img.src = baseHref + "images/icons/mr.png";
											img.size = new YSize(24,25);	// This one is a little different size.
										}
										
										//thisObj.debug.append("Providers: " + obj.lat+" " +obj.lon+" " + obj.display+" <br/>");
							
										var marker = new YMarker(new YGeoPoint(obj.lat, obj.lon), img, obj.id);
										marker.addLabel( "" );
										marker.obj = obj;
										YEvent.Capture(marker, EventsList.MouseClick, function(e) {
													var words = '<div style="width:160px;height:50px; color: black;">'+makehtml(e.thisObj.obj.display)+'</div>';
													e.thisObj.openSmartWindow(words);
												});
										thisObj.map.addOverlay( marker );
										
										thisObj.markers[thisObj.markers.length] = marker;
									} else if (node.nodeName == "r") {
										// Provider
										// NOTE: <r../> is used instead of <RescueRequest../> to cut down on bandwidth
										
										obj.id				= node.getAttribute("id");
										//obj.display		= node.getAttribute("d");	// "d" means "display"
										obj.lat				= node.getAttribute("lat");
										obj.lon				= node.getAttribute("lon");
									
										
										// ===================
										
										var img = new YImage();
										img.src = baseHref + "images/icons/rescue-request.png";
										var marker = new YMarker(new YGeoPoint(obj.lat, obj.lon), img);
										marker.objRef = obj;
										YEvent.Capture(marker, EventsList.MouseDoubleClick, function(){
												window.status = "Loading rescue request...";
												window.location.href = baseHref + "account/member/rescue-requests/request.html?id="+this.objRef.id;
											});
										thisObj.map.addOverlay( marker );
										
										//thisObj.debug.append("RescueRequest: " + obj.lat+" " +obj.lon+" " + obj.display+" <br/>");
								
										thisObj.markers[thisObj.markers.length] = marker;
										
									}
								}
							}
							
						}
					);
			}
		}
	}
	,
	clearMarkers : function() {
		// Removes old
		if ( this.markers != undefined ) {
			for ( var i=0; i < this.markers.length; i++ ) {
				this.map.removeOverlay( this.markers[i] );
			}
		}
		
		this.markers = Array();
	}
	
}






function makehtml(text) {
	var textneu = text.replace(/&/,"&amp;");
	textneu = textneu.replace(/</,"&lt;");
	textneu = textneu.replace(/>/,"&gt;");
	textneu = textneu.replace(/\r\n/,"<br>");
	textneu = textneu.replace(/\n/,"<br>");
	textneu = textneu.replace(/\r/,"<br>");
	return(textneu);
}
/**
 * Determines the absolute x of the given elements
 */
function getOffsetX(node) {
    var result = node.offsetLeft;
    for (var parent = node; parent = parent.offsetParent; parent != null) {
        result += parent.offsetLeft;
    }
    return result;
}
/**
 * Determines the absolute y of the given elements
 */
function getOffsetY(node) {
    var result = node.offsetTop;
    for (var parent = node; parent = parent.offsetParent; parent != null) {
        result += parent.offsetTop;
    }
    return result;
}


function getCheckedValue(radioObj) {
	if(!radioObj)
		return "";
	var radioLength = radioObj.length;
	if(radioLength == undefined)
		if(radioObj.checked)
			return radioObj.value;
		else
			return "";
	for(var i = 0; i < radioLength; i++) {
		if(radioObj[i].checked) {
			return radioObj[i].value;
		}
	}
	return "";
}
function getSelectedValue(selectObj) {
	return selectObj[selectObj.selectedIndex].value;
}







