	
	var isStart = "false";
	var isFinish = "false";
	var pinCount = 1;
	var route = new Array();
	var neutral = new Array();
	var shapes = new Array();
	var ref = new Array();
	var AllRoutes = new Array();
	var selRoute = 0;
	var routeCount = 1;
	
	var sMode = "default";
	var sImage = "";

	// indexOf function added for IE which doesn't support it by default
	if(!Array.indexOf){
	    Array.prototype.indexOf = function(obj){
	        for(var i=0; i<this.length; i++){
	            if(this[i]==obj){
	                return i;
	            }
	        }
	        return -1;
	    }
	}

	// change current mode of map
	function changeMode(sNewMode, sNewImage)
	{
		sMode = sNewMode;
		sImage = sNewImage;
		
		// display the change of mode to the user
		document.getElementById('latest').innerHTML = "Change mode to <strong>" + sMode + "</strong>";
		
		// show or hide the ability to undo the last point drawn
		if (sMode == "Route" || sMode == "Neutralized")
		{
			map.DetachEvent("onclick", plotPin);
			map.AttachEvent("onclick", plotPoly);
			if(document.getElementById('undo_link') != null)
				document.getElementById('undo_link').style.display = "block";
		}
		else
		{
			map.DetachEvent("onclick", plotPoly);
			map.AttachEvent("onclick", plotPin);
			if(document.getElementById('undo_link') != null)
				document.getElementById('undo_link').style.display = "none";
		}
		
		/* in route mode, show all routes avaliable */
		if (sMode == "Route")
		{
			if(document.getElementById('route_links') != null)
			{
				document.getElementById('route_links').style.display = "block";
				document.getElementById('route_current').style.display = "block";
			}
		}
		else
		{
			if(document.getElementById('route_links') != null)
			{
				document.getElementById('route_links').style.display = "none";
				document.getElementById('route_current').style.display = "none";
			}
		}
	}

	function changeRoute(routeID)
	{
		selRoute = routeID;
		
		document.getElementById('route_current').innerHTML = "<br />Currently modifying <strong>route " + (selRoute + 1) + "</strong>.";
		
	}
	// destroys last point in route/neutralized
	function undoLastPoint()
	{
		if (sMode == "Route")
		{
			// has to be a route to undo
			if (AllRoutes.length > 0)
			{
				// has to be a point to undo
				if (AllRoutes[selRoute].length > 0)
				{
					// get instance of selected route
					route = AllRoutes[selRoute].slice(0);
					
					// remove last added point
					route.pop();
					
					// reload new points to array position
					AllRoutes[selRoute] = route.slice();
					
					// redraw all polylines polyline
					for (var i = 0; i < AllRoutes.length; i++)
					{
						DrawPolyShape("route" + i, AllRoutes[i]);
					}
					
					// save to database
					saveRoute();
				}
			}
		}
		else
		{
			// remove last element in array
			neutral.pop();
			// redraw polyline
			DrawPolyShape('neutral', neutral);
			// save to database
			saveNeutral();
		}
	}
	
	function RemovePin(sPinId, sPinMode)
	{
			
		// delete shape if it exists
		if (shapes[ref.indexOf(sPinId.toLowerCase())] != undefined)
		{
			map.DeleteShape(shapes[ref.indexOf(sPinId.toLowerCase())]);
		}
		
		// remove shapes from the array
		shapes.splice(ref.indexOf(sPinId.toLowerCase()), 1);
		ref.splice(ref.indexOf(sPinId.toLowerCase()), 1);
		
		// remove pin in database
		removePinFromDatabase(sPinId, sPinMode);
	}
	
	function plotPin(e)
	{
		// right mouse button click ?
		if (e.rightMouseButton)
		{
			// get point in which mouse cursor was clicked on map
			if (sMode == "Finish" || sMode == "Marshall" || sMode == "Start" || sMode == "KOM" || sMode == "HQ" || sMode == "Feeding Point" || sMode == "Prime" || sMode == "Car Park" || sMode == "Caution")
				var latLong = getLatLong(e, 1);
			else
				var latLong = getLatLong(e, 0);
			
			// draw on map and save to database
			DrawPushPin(pinCount.toString(), latLong);
			savePin(pinCount.toString(), latLong.Latitude, latLong.Longitude);
			pinCount++;
		}
	}
	
	function DrawPushPin(sPinId, latLong)
	{
		// new instance of pushpin shape
		var myPushPin = new VEShape(VEShapeType.Pushpin, latLong);         
		// configure pushpin
		myPushPin.SetTitle(sMode + " Pin"); 
		
		if(document.getElementById('undo_link') != null)
			myPushPin.SetDescription("This is an <strong>" + sMode + "</strong> arrow point. <br /><a href = \"javascript: RemovePin('" + sPinId + "','" + sMode + "')\">Remove this Pin</a>");   
		else
			myPushPin.SetDescription("This is an <strong>" + sMode + "</strong> arrow point.");
		
		myPushPin.SetCustomIcon("<img src='/images/icons/" + sImage + "' />");
		
		// add to map
		map.AddShape(myPushPin);  
		
		// store object in array
		shapes.push(myPushPin);
		ref.push(sPinId.toString().toLowerCase());		
	}
	
	function createRoute(latLong)
	{
		// change selected route
		selRoute = AllRoutes.length;
		
		// empty current route array
		route.length = 0;
		
		// add new point to new array
		route.push(latLong);
		
		// add new route to array containing all routes
		AllRoutes.push(route.slice());
		
		// add new link to change route
		if(document.getElementById('route_links') != null)
			document.getElementById('route_links').innerHTML += "<a href = 'javascript: changeRoute(" + selRoute + ");'>Modify Route " + (selRoute + 1) + "</a><br />";

		
	}
	
	/* function is used when drawing routes from the 
	database when the map is loading **/
	function addPointToRoute(isNew, latLong)
	{
		if (AllRoutes.length != 0)
			route = AllRoutes[selRoute].slice();
		
		// create new route ?
		if (isNew == "1")
			createRoute(latLong);			
		else
			route.push(latLong);
		
		// if this is the first point
		if (AllRoutes.length == 0)
			AllRoutes.push(route.slice());
		else
			AllRoutes[selRoute] = route.slice();		
	}
	
	function plotPoly(e)
	{
		// right mouse button click ?
		if (e.rightMouseButton)
		{
			 // get point in which mouse cursor was clicked on map
			latLong = getLatLong(e, 0);
			
			// add point to array
			if (sMode == "Route")
			{
				if (AllRoutes.length != 0)
					route = AllRoutes[selRoute].slice();
				
				// create new route ?
				if (e.ctrlKey)
					createRoute(latLong);			
				else
					route.push(latLong);
				
				// if this is the first point
				if (AllRoutes.length == 0)
					AllRoutes.push(route.slice());
				else
					AllRoutes[selRoute] = route.slice();
			}
			else
				neutral.push(latLong);
			
			// update parent arrays & save to database
			if (sMode == "Route")
			{
				// draw all routes to map
				for (var i = 0; i < AllRoutes.length; i++)
				{
					DrawPolyShape("route" + i, AllRoutes[i]);
				}
				// save route in database
				saveRoute();
			}
			else
			{
				// draw neutral to map
				DrawPolyShape("neutral", neutral);
				// save neutral in database
				saveNeutral();
			}
		}
	}
	
	// returns a separate copy of an object without reference to the original
	function clone(obj)
	{
	    if(obj == null || typeof(obj) != 'object')
	        return obj;

	    var temp = obj.constructor(); // changed

	    for(var key in obj)
	        temp[key] = clone(obj[key]);
	
	    return temp;
	}

	function DrawPolyShape(pointsID, points)
	{

		// delete any old route/neutral line
		if (shapes[ref.indexOf(pointsID)] != undefined)
		{
			map.DeleteShape(shapes[ref.indexOf(pointsID)]);
		}
		
		// must have more than 1 point to draw a line
		if (points.length > 1)
		{	
			if(ref.indexOf(pointsID) != -1)
			{		
				shapes.splice(ref.indexOf(pointsID), 1);
				ref.splice(ref.indexOf(pointsID), 1);
			}

			// new instance of polyline
			myPolyline = new VEShape(VEShapeType.Polyline, points)
			
			// set polyline properties
			myPolyline.HideIcon();
			
			
			/*** 	LETS CHANGE THE COLOUR OF THE LINES **
					To do this mark change the lines below **
					
					Change the values inside the VEColor() method
					Only change the first three values not the last one
					
					1st Value = Red
					2nd Value = Green
					3rd Value = Blue
					
					values run from 0 to 255 and represent the amount of that colour
					that should be in the final outputted colour
					
					*/
			if (sMode == "Route")
			{
				/** Route Colour */
				myPolyline.SetLineColor(new VEColor(236,125,68,1.0));
			}
			else
			{
				/** Neutral Colour */
				myPolyline.SetLineColor(new VEColor(82,82,212,1.0));
			}
				
			myPolyline.SetLineWidth(2);
			
			// add shape to map
			map.AddShape(myPolyline);
			
			// add shape to arrays
			shapes.push(myPolyline);
			ref.push(pointsID);
		}
	}


	function showArrows()
	{
		if (document.getElementById('arrows').style.display == "block")
			document.getElementById('arrows').style.display = "none";
		else
		{
			document.getElementById('arrows').style.display = "block";
			document.getElementById('pins').style.display = "none";
			document.getElementById('stages').style.display = "none";
		}
	}
	
	function showStages()
	{
		if (document.getElementById('stages').style.display == "block")
			document.getElementById('stages').style.display = "none";
		else
		{
			document.getElementById('stages').style.display = "block";
			document.getElementById('pins').style.display = "none";
			document.getElementById('arrows').style.display = "none";
		}
	}
	
	function showPins()
	{
		if (document.getElementById('pins').style.display == "block")
			document.getElementById('pins').style.display = "none";
		else
		{
			document.getElementById('pins').style.display = "block";		
			document.getElementById('arrows').style.display = "none";
			document.getElementById('stages').style.display = "none";
		}
	}

	function setPinCount(iNumber)
	{
		pinCount = iNumber + 1;
	}
	
	
	function getLatLong(e, iArrow)
	{
		if(document.body.scrollTop != undefined && document.body.scrollTop != "0")
		{
			sScroll = document.body.scrollTop;
		}
		else if(window.pageYOffset != undefined && window.pageYOffset != "0")
		{
			sScroll = window.pageYOffset;
		}
		else if(document.documentElement.scrollTop != undefined && document.documentElement.scrollTop != "0")
		{
			sScroll = document.documentElement.scrollTop;
		}
		else
		{
			sScroll = 0;
		}
		
		if (iArrow == 1)
			pixel = new VEPixel(e.mapX, e.mapY - 17);		
		else
			pixel = new VEPixel(e.mapX, e.mapY);
		return map.PixelToLatLong(pixel);
	}
	
	/***** Database Calls *******/

	function saveRoute()
	{	
		sRoute = AllRoutes[selRoute].join(";")
		
		var xmlDoc=null;
	
		if (window.XMLHttpRequest)
		{
			xmlDoc=new XMLHttpRequest();
		}
		else if (window.ActiveXObject)
		{
			xmlDoc=new ActiveXObject("Microsoft.XMLHTTP");
		}
		
		xmlDoc.open( "GET", "ajax/save_route.asp?x=" + Math.random() + "&route=" + sRoute + "&routeno=" + selRoute);
	
		xmlDoc.onreadystatechange=function()
		{
			if (xmlDoc.readyState==4)
			{
				document.getElementById("latest").innerHTML = xmlDoc.responseText;
			}
		}		
		
		xmlDoc.send( null );	
	}


	function saveNeutral()
	{	
		sNeutral = neutral.join(";")
		var xmlDoc=null;
	
		if (window.XMLHttpRequest)
		{
			xmlDoc=new XMLHttpRequest();
		}
		else if (window.ActiveXObject)
		{
			xmlDoc=new ActiveXObject("Microsoft.XMLHTTP");
		}
		
		xmlDoc.open( "GET", "ajax/save_neutrals.asp?x=" + Math.random() + "&neutrals=" + sNeutral);
	
		xmlDoc.onreadystatechange=function()
		{
			if (xmlDoc.readyState==4)
			{
				document.getElementById("latest").innerHTML = xmlDoc.responseText;
			}
		}		
		
		xmlDoc.send( null );	
	}

	function savePin(pinID, sLat, sLon)
	{	
		var xmlDoc=null;
	
		if (window.XMLHttpRequest)
		{
			xmlDoc=new XMLHttpRequest();
		}
		else if (window.ActiveXObject)
		{
			xmlDoc=new ActiveXObject("Microsoft.XMLHTTP");
		}
		
		xmlDoc.open( "GET", "ajax/save_pin.asp?x=" + Math.random() + "&pin=" + pinID + "&type=" + sMode + "&lon=" + sLon + "&lat=" + sLat);
	
		xmlDoc.onreadystatechange=function()
		{
			if (xmlDoc.readyState==4)
			{
				document.getElementById("latest").innerHTML = xmlDoc.responseText;
			}
		}		
		
		xmlDoc.send( null );	
	}
	
	function removePinFromDatabase(pinID, sType)
	{
		var xmlDoc=null;
	
		if (window.XMLHttpRequest)
		{
			xmlDoc=new XMLHttpRequest();
		}
		else if (window.ActiveXObject)
		{
			xmlDoc=new ActiveXObject("Microsoft.XMLHTTP");
		}
		
		xmlDoc.open( "GET", "ajax/remove_pin.asp?x=" + Math.random() + "&pin=" + pinID + "&type=" + sType);
	
		xmlDoc.onreadystatechange=function()
		{
			if (xmlDoc.readyState==4)
			{
				document.getElementById("latest").innerHTML = xmlDoc.responseText;
			}
		}		
		
		
		xmlDoc.send( null );			
	}