// Global Variables
var bodyLoad = null;        // Body load function
var bodyUnload = null;      // Body unload function
var map = null;             // Google map object
var maxLocations = 150;     // Maximum number of locations that will be displayed 
var sponsLoc = new Array(); // Contains all the sponsor locations
var total = 0;              // The total number of locations in the current map area
var xmlHttp = null;         // XmlHttpRequest
var logoUri = null;
var logoImage = null;

// For directions
var markerID = 0;
var gmarkers = [];
var htmls = [];
var to_htmls = [];
var from_htmls = [];

//Class representing an individual location
function SponsorLocation(sID, sname, address1, address2, city, state, zip, id, LatLong, pushPinID)
{	
	this.sID = sID;
	this.sname = sname;
	this.address1 = address1;
	this.address2 = address2;
	this.city = city;
	this.state = state;
	this.zip = zip;
	this.id = id;
	this.LatLong = LatLong;
	this.checked = Boolean(false);
	this.pushpin = pushPinID;
}

//This function replaces the BODY OnLoad funtion with our own
function hookBodyOnLoad()
{	
	bodyLoad = window.onload;
	boyUnload = window.onunload;
	window.onload = Load;
	window.onunload = Unload;
}

//This new OnLoad function calls both the original and the one we want to append
function Load()
{	
	if(bodyLoad)
		bodyLoad();
		
	InitializeMap();
	InitializeXmlHttpRequest();
	
	var sponsorid = $.query.get('sponsorid');

	logoUri = 'https://images.childrensmiraclenetwork.org/Sponsor/Thumbnails/' + sponsorid + '.png';
	logoImage = new Image();
	logoImage.src = logoUri;
	
	// After initialization, send the original request to get all the sponsor locations
	SendRequest('');           
}

//This new OnUnLoad function calls both the original and the one we want to append
function Unload()
{
	if(bodyUnload)
		bodyUnload();
		
	GUnload();
}

//Initializes the XmlHttpRequest object
function InitializeXmlHttpRequest()
{
	try
	{	    
		if (window.XMLHttpRequest)
		{
		    // Firefox, Opera 8.0+, Safari
			xmlHttp = new XMLHttpRequest();
		}
		else if (window.ActiveXObject)
	    {
	        // Internet Explorer
			xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
		}
		else 
		    alert('Your browser cannot handle this script');
		    
		xmlHttp.onreadystatechange = XmlHttpStateChanged;
	}
	catch (ex)
	{
		alert('error Initializing Ajax: ' + ex.name + '  ' + ex.message );
	}
}

// XMLHttpRequest state changed handler
function XmlHttpStateChanged()
{
	//Event Handler for when the xml is ready to be parsed
	try
	{
		if (xmlHttp.readyState == 4 && xmlHttp.status == 200)
		{
			if (xmlHttp.responseXML != null)
			{
				var xmlDoc = xmlHttp.responseXML;   // Get the response from the .ashx
				ParseLocXMLDoc(xmlDoc);             // Parse the response from the .ashx
				InitializeXmlHttpRequest();         // Re-initalize the XMLHttpRequest
			}
		}
		else if (this.readyState == 4 && this.status != 200)
			document.getElementById('message').innerHTML = 'Error Retrieving locations from the database.<br />Please try again.';
	}
	catch (ex)
	{
		alert('error in Xml HTTP State Changed Event handler: ' + ex.name + '  ' + ex.message );
	}
}

// Sends a request to the .ashx
function SendRequest(requestString)
{
 	try
	{	
		xmlHttp.open('POST', 'handlers/MapRequest.ashx', true);
		xmlHttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
		xmlHttp.send(requestString);
	}
	catch (ex)
	{
		alert('error in SendRequest: ' + ex.name + '  ' + ex.message );
	}
}
     
// Initializes the Google Map   
function InitializeMap()
{
	//Google Account Credentials:  Account Name - "childrensmiraclenetwork" Password - "osmond~4525"  GMail address: "childrensmiraclenetwork@gmail.com"
	//API Key for MiracleSoup: ABQIAAAA7z6za-3cyf4-ya1Q3nC5eBQVv_0ZTFfCjQd9ujxZ9GTvFTrw1BSBXQB0k1Afsg5FoZj_O81S2cqWgQ
	//API Key for MiracleSoup/articles: ABQIAAAA7z6za-3cyf4-ya1Q3nC5eBQiaHFlcmgtyUfaAght2KCH_n1M7RRgdIpA6EuW9_5-GSO4U8nAqd2ffw
	//API Key for TestMiracleSoup: ABQIAAAA7z6za-3cyf4-ya1Q3nC5eBQs08WOXY_M4dQWsgYZA4b9izn1FxTBCnIZCTcJzbehEgJAAKBx065rMQ
	//API Key for TestMiracleSoup/articles: ABQIAAAA7z6za-3cyf4-ya1Q3nC5eBTZ8uutQkt2FH3wGNeBfhrzN-eH8BTy24FaBUWYpaeA6BHMkFxLpxsUcw
	//API Key for localhost: ABQIAAAA7z6za-3cyf4-ya1Q3nC5eBQGao5QJyesy0__Xybc6Bk3-KhbwhQanKtf4T29S4hDPjSub9w1GkaWIw
	//API Key for storage.childrensmiraclenetwork.org: ABQIAAAA7z6za-3cyf4-ya1Q3nC5eBTtWMfyzgqE6EUd6pKKIW4ZIr6NaBSB2VCy8XsnLfbQeSwQs1v3zEsUqw
	if (GBrowserIsCompatible())
	{
	    // Create and setup map
		map = new GMap2(document.getElementById("mapCanvas"));
		map.setCenter(new GLatLng(40, -99), 3);		
		map.addControl(new GSmallMapControl());
		map.addControl(new GMapTypeControl());
		map.enableScrollWheelZoom();
		map.enableDoubleClickZoom();
		map.enableContinuousZoom();
		
		// Bind events.  Use dragend and zoomend so that the location information does not disappear if the info bubble
		// pans the map.  Using moveend will break this functionality.
		GEvent.bind(this.map, "dragend", this, MapViewChanged);
		GEvent.bind(this.map, "zoomend", this, MapViewChanged);

		// Create a base icon for all of our markers that specifies the shadow, icon dimensions, etc.
		var baseIcon = new GIcon();
		baseIcon.shadow = "https://images.childrensmiraclenetwork.org/Sponsor/Thumbnails/shadowMarker.png";
		baseIcon.iconSize = new GSize(30, 35);
		baseIcon.shadowSize = new GSize(37, 35);
		baseIcon.iconAnchor = new GPoint(9, 35);
		baseIcon.infoWindowAnchor = new GPoint(16, 0);
	}
}

// Parses locations send from the .ashx
function ParseLocXMLDoc(xmlDoc)
{
	// Populates the sponsors and sponsLoc lists from the xml document
	try
	{
		// Get a list of sponsor locations.
		var x = xmlDoc.getElementsByTagName('Table');
 
        // Get the total number of sponsors
		total = sponsLoc.length + x.length;

		// Only enter the max number of locations to the list
		var xmlLength = 0;
		xmlLength = x.length;
		
		if (xmlLength > maxLocations)
			xmlLength = maxLocations;

        // If there are more locations than the max, inform the user that location information will
        // be truncated to the max number of locations
		if (total > maxLocations)
		{
			xmlLength = maxLocations - sponsLoc.length;

			if (total == x.length)
			{
				document.getElementById('message').innerHTML = 'There are too many locations to display.<br />Displaying the first ' +
					maxLocations + ' locations in the list ...<br />(Please zoom in to view locations for this selection.)';
			}
			else
			{
				document.getElementById('message').innerHTML = '';					
			}
		}

        // Iterate through all the sponsor information and load it into the sponsor and sponsor location objects
		for (var i = 0;i < xmlLength; i++)
		{
			if ((x[i].getElementsByTagName('Sponsor')[0] != null) && (x[i].getElementsByTagName('Sponsor')[0].childNodes[0] != null))
				var sID = RemoveBadChars(x[i].getElementsByTagName('Sponsor')[0].childNodes[0].nodeValue);
			else 
			    var sID = '';
			    
			if ((x[i].getElementsByTagName('SponsorName')[0] != null) && (x[i].getElementsByTagName('SponsorName')[0].childNodes[0] != null))
				var sname = RemoveBadChars(x[i].getElementsByTagName('SponsorName')[0].childNodes[0].nodeValue);
			else 
			    var sname = '';
			    
			if ((x[i].getElementsByTagName('ID')[0] != null) && (x[i].getElementsByTagName('ID')[0].childNodes[0] != null))
				var id = RemoveBadChars(x[i].getElementsByTagName('ID')[0].childNodes[0].nodeValue);
			else 
			    var id = 'sponsLoc' + i;
			    
			if ((x[i].getElementsByTagName('MailAddress1')[0] != null) && (x[i].getElementsByTagName('MailAddress1')[0].childNodes[0] != null))
				var sLocAddress1 = RemoveBadChars(x[i].getElementsByTagName('MailAddress1')[0].childNodes[0].nodeValue);
			else 
			    var sLocAddress1 = '';
			    
			if ((x[i].getElementsByTagName('MailAddress2')[0] != null) && (x[i].getElementsByTagName('MailAddress2')[0].childNodes[0] != null))
				var sLocAddress2 = RemoveBadChars(x[i].getElementsByTagName('MailAddress2')[0].childNodes[0].nodeValue);
			else 
			    var sLocAddress2 = '';
			    
			if ((x[i].getElementsByTagName('MailCity')[0] != null) && (x[i].getElementsByTagName('MailCity')[0].childNodes[0] != null))
				var sLocCity = RemoveBadChars(x[i].getElementsByTagName('MailCity')[0].childNodes[0].nodeValue);
			else 
			    var sLocCity = '';
			    
			if ((x[i].getElementsByTagName('MailState')[0] != null) && (x[i].getElementsByTagName('MailState')[0].childNodes[0] != null))
				var sLocState = RemoveBadChars(x[i].getElementsByTagName('MailState')[0].childNodes[0].nodeValue);
			else 
			    var sLocState = '';
			    
			if ((x[i].getElementsByTagName('MailZipCode')[0] != null) && (x[i].getElementsByTagName('MailZipCode')[0].childNodes[0] != null))
				var sLocZipCode = RemoveBadChars(x[i].getElementsByTagName('MailZipCode')[0].childNodes[0].nodeValue);
			else 
			    var sLocZipCode = '';
			    
			if ((x[i].getElementsByTagName('Latitude')[0] != null) && (x[i].getElementsByTagName('Latitude')[0].childNodes[0] != null))
				var sLocLatitude = parseFloat(x[i].getElementsByTagName('Latitude')[0].childNodes[0].nodeValue);
			else 
			    var sLocLatitude = 0;
			    
			if ((x[i].getElementsByTagName('Longitude')[0] != null) && (x[i].getElementsByTagName('Longitude')[0].childNodes[0] != null))
				var sLocLongitude = parseFloat(x[i].getElementsByTagName('Longitude')[0].childNodes[0].nodeValue);
			else 
			    var sLocLongitude = 0;
			    
			if (logoUri == '')
		    {
		        if ((x[i].getElementsByTagName('URI')[0] != null) && (x[i].getElementsByTagName('URI')[0].childNodes[0] != null)) {
		            logoUri = x[i].getElementsByTagName('URI')[0].childNodes[0].nodeValue;
		        }
            }
			    
			if (sLocLatitude == 0 || sLocLongitude == 0 || sLocLatitude == null || sLocLongitude == null)
				var sLatLong = null;
			else 
			    var sLatLong = new GLatLng(sLocLatitude, sLocLongitude);

			if (sLatLong != null)
			{
				var addLoc = new Boolean(true);
				
				// Make sure the sponsor location doesn't already exist
				for (var j in sponsLoc)
				{
					if (sponsLoc[j].id == id)
					{
						addLoc = false;
						break;
					}
				}
				
				// If the location doesn't exist, then add it to the array with all the sponsor info,
				// and then create the marker on the map
				if (addLoc == true)
				{
					// Create a new sponsor location and add a pin to the map.
					var pushPinID = '';
					var where = '';
					
					if (sLocAddress1 != '')
						where += sLocAddress1 + '<br />';
						
					if (sLocAddress2 != '')
						where += sLocAddress2 + '<br />';
						
					where += sLocCity + ', ' + sLocState + ' ' + sLocZipCode;

                    // Create and add the location to the array.
					sponsLoc[sponsLoc.length] = new SponsorLocation(sID, sname, sLocAddress1, sLocAddress2, sLocCity, sLocState, sLocZipCode, id, sLatLong, pushPinID);

                    // Add the market to the map.
					map.addOverlay(createMarker(sLatLong, sname, sID, where));
				}
			}
		}
	}
	catch (ex)
	{
		alert('error Parsing XML: ' + ex.name + '  ' + ex.message );
	}
}

// Gets the direction info and loads it in a new window
function getDirections() 
{
    var saddr = document.getElementById("saddr").value
    var daddr = document.getElementById("daddr").value
    var gDir = new GDirections(map, document.getElementById("directions"));
    gDir.load("from: " + saddr + " to: " + daddr, {getPolyline:true});
}
 
// This function picks up the click and opens the corresponding info window
function myclick(i) 
{
    gmarkers[i].openInfoWindowHtml(htmls[i]);
}

// functions that open the directions forms
function tohere(i) 
{
    gmarkers[i].openInfoWindowHtml(to_htmls[i]);
}

function fromhere(i) 
{
    gmarkers[i].openInfoWindowHtml(from_htmls[i]);
}
    
// Creates a marker on the map  
function createMarker(point, sname, sID, where)
{
	try
	{
		// Get the logo from the logos folder
		//var logoImage = new Image();
		//logoImage.src = "/images/logos/" + sID + ".png";
		//logoImage.src = logoUri;
		
		// Modify the size of the logo.  The logo needs to be smaller from the wider zoom and
		// increase in size as the map is zoomed in until the logo is its original size.
		// Start with the logo 25% its original size. 
		var logoHeight = logoImage.height / 4;
		var logoWidth = logoImage.width / 4;
		
		// If the map is zoomed in then the logo needs to start to grow.
		if (map.getZoom() > 3)
	    {	        
	        // Make the logo 25% * 1/2 the zoom level 
	        logoHeight = logoHeight * (map.getZoom() * .5);		        		        
		    logoWidth = logoWidth * (map.getZoom() * .5);
		    
		    // If the new width and height is greater than the logos orignal size,
		    // then this will be the max for the logo, so set it to its original size
		    if (logoHeight > logoImage.height || logoWidth > logoImage.width)
		    {
		        logoHeight = logoImage.height;
	            logoWidth = logoImage.width;    	           
		    }	
		}
	    
	    // Create an icon for this point using the base icon class
	    var logoIcon = new GIcon();
		logoIcon.image = logoImage.src;
		logoIcon.iconSize = new GSize(logoWidth, logoHeight);
		logoIcon.shadowSize = new GSize(logoImage.width, logoImage.height);
		logoIcon.iconAnchor = new GPoint(0,0);
		logoIcon.infoWindowAnchor = new GPoint((logoImage.height / 2), 0);

		// Set up our GMarkerOptions object
		var markerOptions = { icon:logoIcon, title:sname + " \r\n" + where.replace("<br />", "\r\n").replace("<br />", "\r\n") };		
		var marker = new GMarker(point, markerOptions);

        // Add the directions links and markup to the bubble
        var html = '';
        
        // The info window version with the "to here" form open
        to_htmls[markerID] = html + '<br>Directions: <b>To here</b> - <a href="javascript:fromhere(' + markerID + ')">From here</a>' +
           '<br>Start address:<form action="http://maps.google.com/maps" method="get" target="_blank">' +
           '<input type="text" SIZE=40 MAXLENGTH=40 name="saddr" id="saddr" value="" /><br>' +
           '<INPUT value="Get Directions" TYPE="SUBMIT">' +
           '<input type="hidden" name="daddr" value="' + point.lat() + ',' + point.lng() + 
           '"/>';
           
        // The info window version with the "to here" form open
        from_htmls[markerID] = html + '<br>Directions: <a href="javascript:tohere(' + markerID + ')">To here</a> - <b>From here</b>' +
           '<br>End address:<form action="http://maps.google.com/maps" method="get"" target="_blank">' +
           '<input type="text" SIZE=40 MAXLENGTH=40 name="daddr" id="daddr" value="" /><br>' +
           '<INPUT value="Get Directions" TYPE="SUBMIT">' +
           '<input type="hidden" name="saddr" value="' + point.lat() + ',' + point.lng() +
           '"/>';
           
        // The inactive version of the direction info
        html = html + '<br>Directions: <a href="javascript:tohere(' + markerID + ')">To here</a> - <a href="javascript:fromhere(' + markerID + ')">From here</a>';
        
        // Wire up the click listener for the logo to open the info bubble
		GEvent.addListener(marker, "click", function() {
		    if (map.getZoom() >= 4)
		    {
		        map.panTo(marker.getPoint());
			    marker.openInfoWindowHtml("<b>" + sname + "</b><br />" + where + "<br />" +  html);			    
			}
		});
		
		// Add the marker and markup to the array
		gmarkers[markerID] = marker;
        htmls[markerID] = html;
        
        // Increment the number of markers
        markerID++;
        
        // If the total locations are less than the max locations, don't display info after
        // the locations are loaded. 
        if (total < maxLocations)
            document.getElementById('message').innerHTML = '';
            
		return marker;
	}
	catch (ex)
	{
		alert('error creating map marker: ' + ex.name + '  ' + ex.message );
	}
}

// The event handler for zoomend or dragend
function MapViewChanged()
{
	//Event handler for when the map view change occurs
	try
	{
		document.getElementById('message').innerHTML = 'Retrieving locations ... <br />Please wait ...';
		
		//Clear out the sponsor location array
		sponsLoc = new Array();
		
		//Clear the map
		map.clearOverlays();
		
		//Build a request string based on the selected sponsors and the current map view
		var selectedSponsorString = '';
		
		// Get the lats/longs for each the corners of the map
		var rect = map.getBounds();
		var southWest = rect.getSouthWest();
		var northEast = rect.getNorthEast();

        // Build the request for the .ashx
		var requestString = 'Lat1=' + southWest.lat() + '&Lon1=' + southWest.lng() + '&Lat2=' + northEast.lat() + '&Lon2=' + northEast.lng();

        // Call the .ashx to get the locations for the viewable area
		SendRequest(requestString);										
	}
	catch (ex)
	{
		alert('error in Map View Changed Event handler: ' + ex.name + '  ' + ex.message );
	}
}

// Removes bad characters from the location info
function RemoveBadChars(sponsorString)
{
	try
	{
		var out = '';
		var add = '';
		var returnString = '' + sponsorString;

		var charArray = new Array('&','@','#','\'','"','(',')',';','-',',',':','.','+','=','%','[',']','{','}','<','>','~','`','!','$','%','^','*','/','?','\\');

		for (var i = 0; i <= charArray.length; i++)
		{
			out = charArray[i];

			while (returnString.indexOf(out)>-1)
			{
				var pos = returnString.indexOf(out);
				returnString = '' + (returnString.substring(0, pos) + add + returnString.substring((pos + out.length), returnString.length));
			}
		}

		return returnString;
	}
	catch (ex)
	{
		alert('error in RemoveBadChars: ' + ex.name + '  ' + ex.message );
	}
}