function LineManager(application,units,distanceDiv,HttpClientPost) {
	
	// LINES VARIABLES												************************************************************
	this.lines = new Array();									// array of GPolyline objects
	this.linePoints = new Array();						// array of all the points in the map
	this.lastPoint = false;										// last point clicked
	this.startPoint = false;									// starting point object reference
	this.startMarker = false;									// start marker object reference
	this.totalDistance = 0;										// total distance for the current route
	this.distanceString = "";									// distance string to use for the graph
	this.metric = units;											// default units are meters, false = english units
	this.totalDistanceDiv = distanceDiv;			// div to update the total distance in
	map = application.map;										// reference to the Google Map object
	client = HttpClientPost;									// HttpClientPost object for ajax calls


	// CUSTOM MARKERS VARIABLES								************************************************************
	this.markerActive = false;								// flag to allow line drawing or placing of location markers
	this.markersCount = 0;										// count of the markers that are on the map, used for indexing
	this.iconType = "";												// the icon type to be placed on the map
	markers = new Array();										// array of all the marker objects
	markersText = new Array();								// array of all the text associated with the markers
	markerVariableText = "markertext";				// name for the buttons, text boxes, etc. related to the markers
	markerClickListeners = new Array();				// array of click event listeners that will be removed upon marker removal
	markerMouseOverListeners = new Array();		// array of mouse over event listeners that will be removed upon marker removal
	markerMouseOutListeners = new Array();		// array of mouse out event listeners that will be removed upon marker removal
		
	
	
}

LineManager.prototype = {
	
	manageClick: function (point){
		
		if(point != undefined){
			
			if(this.markerActive){
				
				this.addicon(point,this.markersCount);
			}else{
				document.getElementById("alertbox").innerHTML = "drawing line";
				this.addline(point);
				this.checkLocation(point);
				this.updateDistance();
			}
		}
		
	},
	
	toggleIcon: function (icon) {
		
		if(this.markerActive && this.iconType == icon){
			
			this.markerActive = false;
			this.iconType = "";
		
			document.getElementById("alertbox").innerHTML = "drawing line";
			
		}else{
			this.markerActive = true;
			this.iconType = icon;
			
			document.getElementById("alertbox").innerHTML = icon+ " active";
		}
		
	},
	
	saveMarkerText: function (marker) {
		
		//alert(marker);
		var newText = document.getElementById(markerVariableText+marker).value;
		markersText[marker] = newText;
		markers[marker].closeInfoWindow();
		
	},
	
	addicon: function (point,markerNum) {
		
		var newIcon;
		var newMarker;
		var iconImageFile = "images/"+this.iconType+".png";
		var iconImageShadowFile = "images/startshadow.png";
		
		var iconClickListener;
		var iconMouseOverListener;
		var iconMouseOutListener;
		
		var notesTab;
		var notesHTML;
		var removeTab;
		var removeHTML;
		
		newIcon = new GIcon();
		newIcon.image = iconImageFile;
		newIcon.iconSize = new GSize(40,45);
		newIcon.iconAnchor = new GPoint(17,37);
		newIcon.shadow = iconImageShadowFile;
		newIcon.shadowSize = new GSize(65,28);
		newIcon.infoWindowAnchor = new GPoint(17,37); 
		
		newMarker = new GMarker(point, {icon:newIcon,dragCrossMove:true,draggable:true,title:this.iconType});
		
		
		iconClickListener = GEvent.addListener(newMarker,"click", function () {
																																						
			notesHTML = "<div style='margin:5px;'><h3>Notes</h3><textarea id='"+markerVariableText+markerNum+"' name='"+markerVariableText+markerNum+"'>"+markersText[markerNum]+"</textarea><br/><br/><button type='button' onclick='LineManager.saveMarkerText("+markerNum+");'>Save</button></div>";
			
			removeHTML = "<div style='margin:5px;'><h3>Remove</h3>Click below to remove this marker.<br/><br/><a href='#' onclick='LineManager.removeicon("+markerNum+");'>Remove</a></div>";
			
			notesTab = new GInfoWindowTab("Notes",notesHTML);
			removeTab = new GInfoWindowTab("Remove",removeHTML);
			
			var testArray = new Array(notesTab, removeTab);
			
			newMarker.openInfoWindowTabsHtml(testArray);
			
		});
		
		iconMouseOverListener = GEvent.addListener(newMarker,"mouseover", function () {
			
			this.setImage("images/hover_"+this.getTitle()+".png");
			
		});
		
		iconMouseOutListener = GEvent.addListener(newMarker,"mouseout", function () {
			
			this.setImage("images/"+this.getTitle()+".png");
			
		});
		
		iconMouseOutListener = GEvent.addListener(newMarker,"infowindowopen", function () {
			
			map.panTo(this.getPoint());
			
		});
		
		
		
		
		markersText.push(this.iconType);
		markers.push(newMarker);
		markerClickListeners.push(iconClickListener);
		markerMouseOverListeners.push(iconMouseOverListener);
		markerMouseOutListeners.push(iconMouseOutListener);
		
		map.addOverlay(newMarker);
				
		this.markersCount++;
		this.toggleIcon(this.iconType);
		this.checkLocation(point);
	},
	
	removeicon: function (iconid) {

		GEvent.removeListener(markerClickListeners[iconid]);
		GEvent.removeListener(markerMouseOverListeners[iconid]);
		GEvent.removeListener(markerMouseOutListeners[iconid]);
		map.removeOverlay(markers[iconid]);
		
		markers[iconid] = null;
		markersText[iconid] = null;

	},
	
	
	addline: function (point) {
		
		var polyline;
		var startIcon;
		var startImageFile = "images/start.png";
		var startImageShadowFile = "images/startshadow.png";
		
		this.linePoints.push(point);
		
		if(this.lastPoint != false){
			polyline = new GPolyline([this.lastPoint,point], "#0000ff", 4,.55,{clickable:false});
			this.lines.push(polyline);
			map.addOverlay(polyline);
			
		}else{
			
			this.startPoint = this.pointToGLatLng(point);
			
			startIcon = new GIcon();
			startIcon.image = startImageFile;
			startIcon.iconSize = new GSize(43,37);
			startIcon.iconAnchor = new GPoint(17,37);
			startIcon.shadow = startImageShadowFile;
			startIcon.shadowSize = new GSize(65,28);
			
			this.startMarker = new GMarker(point, {icon:startIcon});
			map.addOverlay(this.startMarker);
			
		}
		this.lastPoint = point;
		
		
	},
	
	pointToGLatLng: function (point) {
		
		var returnPoint;
		var clickCoords;
		var commaPos;
		var endPos;
		var lat;
		var lng;
		
		clickCoords = point;
		clickCoords +="";
		commaPos = clickCoords.indexOf(",");
		endPos = clickCoords.indexOf(")");
		lat = Number(clickCoords.substring(1,commaPos));
		lng = Number(clickCoords.substring(commaPos+2,endPos));
		returnPoint = new GLatLng(lat,lng);
		
		return returnPoint;
		
	},
	
	checkLocation: function (point) {
		
		var clickCoords;
		var commaPos;
		var endPos;
		var x;
		var y;
		var minX;
		var maxX;
		var minY;
		var maxY;
		var currentBounds;
		var southWest;
		var southEast;
		var panTolerance = 95;					// how close to the border before we re-center the view (px)
		
		clickCoords = map.fromLatLngToDivPixel(point);
		clickCoords +="";
		commaPos = clickCoords.indexOf(",");
		endPos = clickCoords.indexOf(")");
		x = Number(clickCoords.substring(1,commaPos));
		y = Number(clickCoords.substring(commaPos+2,endPos));

		currentBounds = map.getBounds();
		
		southWest = map.fromLatLngToDivPixel(currentBounds.getSouthWest());
		southWest +="";
		commaPos = southWest.indexOf(",");
		endPos = southWest.indexOf(")");
		minX = Number(southWest.substring(1,commaPos));
		maxY = Number(southWest.substring(commaPos+2,endPos));
		
		northEast = map.fromLatLngToDivPixel(currentBounds.getNorthEast());
		northEast +="";
		commaPos = northEast.indexOf(",");
		endPos = northEast.indexOf(")");
		maxX = Number(northEast.substring(1,commaPos));
		minY = Number(northEast.substring(commaPos+2,endPos));
		
		
		if(maxX - x <= panTolerance || maxY - y <= panTolerance || x - panTolerance <= minX || y - panTolerance <= minY ){
			
			map.panTo(point);
			
		}
		
		
	},
	
	undo: function () {
		var linePointsLength = this.linePoints.length;
		
		if(this.lines.length == 0){
				
			map.removeOverlay(this.startMarker);
			
			
			for(i=0; i <= linePointsLength;i++){
				this.linePoints.pop();
			}
			
			
			this.startMarker = false;
			this.startPoint = false;
			this.lastPoint = false;
			
		}
		
		
		
		if(this.lines.length > 0){

			map.removeOverlay(this.lines[this.lines.length-1]);
			this.linePoints.pop();
			this.lines.pop();
			this.lastPoint = this.linePoints[this.linePoints.length-1];
			
			this.checkLocation(this.lastPoint);
			this.updateDistance();
			
		}
	},
	
	
	
	clearAll: function () {
		var linePointsLength = this.linePoints.length;
		var linesLength = this.lines.length;
		var markersLength = markers.length;
		var markersTextLength = markersText.length;
		var markerClickListenersLength = markerClickListeners.length;
		var markerMouseOverListenersLength = markerMouseOverListeners.length;
		var markerMouseOutListenersLength = markerMouseOutListeners.length;
			
		if(confirm("Are you sure you want to clear everything? This action cannot be undone. ")){
			
			for(i=0; i <= linePointsLength;i++){
				this.linePoints.pop();
			}
			
			for(i=0; i <= linesLength;i++){
				this.lines.pop();
			}
			
			
			if(this.markersCount > 0){
			
				for(i=0; i <= markersTextLength;i++){
					markersText.pop();
				}
				
				for(i=0; i <= markersLength;i++){
					markers.pop();
				}
				
				for(i=0; i <= markerClickListenersLength;i++){
					//GEvent.removeListener(markerClickListeners[markerClickListeners.length-1]);
					markerClickListeners.pop();
				}
			
				
				for(i=0; i <= markerMouseOverListenersLength;i++){
					//alert("poppie poo");
					//GEvent.removeListener(markerMouseOverListeners[markerMouseOverListeners.length-1]);
					markerMouseOverListeners.pop();
				}
				
				for(i=0; i <= markerMouseOutListenersLength;i++){
					//alert("poppy woppie");
					//GEvent.removeListener(markerMouseOutListeners[markerMouseOutListeners.length-1]);
					markerMouseOutListeners.pop();
				}
					
			}
			
			
			
			this.startMarker = false;
			this.startPoint = false;
			this.lastPoint = false;
			this.markerActive = false;
			this.markersCount = 0;
			this.nextMileMarker = this.mileMarkerIncrement;
			
			map.clearOverlays();
			this.updateDistance();
		}
		
		
	},
	
	toggleUnits: function (units) {
		
		(units == "metric") ? this.metric = true : this.metric = false;
		this.updateDistance();
		
	},
	
	calculateDistance: function () {
		
		var totalDistance = 0;
		var lastPoint;
		var currentPoint;
		
		if(this.startPoint){
			
			lastPoint = this.startPoint;
			
			for(i=1;i < this.linePoints.length;i++){
				
				currentPoint = this.pointToGLatLng(this.linePoints[i]);
				totalDistance = totalDistance + lastPoint.distanceFrom(currentPoint);
				lastPoint = this.pointToGLatLng(this.linePoints[i]);
				
												
			}
			
			(this.metric) ? totalDistance = totalDistance/1000 : totalDistance = totalDistance*0.000621371192;
			
			return totalDistance;
		}else{
			
			return 0;
		}
		
	},
	
	calculateFinalDistance: function () {
		
		var totalDistance = 0;
		var tempDistance = 0;
		var lastPoint;
		var currentPoint;
		
		if(this.startPoint){
			
			lastPoint = this.startPoint;
			
			this.distanceString = tempDistance;
			
			for(i=1;i < this.linePoints.length;i++){
				
				currentPoint = this.pointToGLatLng(this.linePoints[i]);
				totalDistance = totalDistance + lastPoint.distanceFrom(currentPoint);
				lastPoint = this.pointToGLatLng(this.linePoints[i]);
				
				this.distanceString += "|"+totalDistance*0.000621371192;
				
			}
			
			totalDistance = totalDistance*0.000621371192;
			
			return totalDistance;
		}else{
			
			return 0;
		}
		
	},
	
	
	updateDistance: function () {
		
		var totalDistance;
		var units;
		
		(this.metric) ? units = "km" : units = "miles";
		this.totalDistance = this.calculateDistance();
		
		
		document.getElementById(this.totalDistanceDiv).innerHTML = this.totalDistance.toFixed(2) + " " + units;
		
	},
	
	
	loop: function () {
		
		if(this.lines.length > 0 && this.lastPoint != this.startPoint){
			
			this.addline(this.startPoint);
			
		}
		
	},
	
	outBack: function () {
		
		var tempPoints = this.linePoints.slice(0);
		
		if(this.lines.length > 0){
			
			for(j=tempPoints.length;j > 1;j--){
				
				this.addline(tempPoints[j-2]);
				
			}
			
			map.panTo(this.startPoint);
		}
		
	},
	
	printTheSave: function () {
		
		var pointsHTML="";
		var markersHTML="";
		var distanceHTML="";
		var routeDescription="";
		var routeTitle="";
		var divHTML="";
		var distance;
		var units;
		var area_id;
		var error = false;
		
		//print the points
		if(this.linePoints.length > 1) {
			for(i=0;i < this.linePoints.length; i++) {
				
				pointsHTML += this.linePoints[i]+"|";
				
			}
			
			pointsHTML = pointsHTML.substring(0,pointsHTML.length-1);
			
			
			//print the total distance
		
			distance = this.calculateFinalDistance();
			(this.metric) ? units = "km" : units = "miles";
			
			//alert(distancetHTML);
			
		}else{
			
			error = true;
			alert("You have to draw a route before you can save it.");
			
		}
		
		
		
		//print icons (title,location,description)
		if (this.markersCount > 0) {
			
			for (i=0; i < this.markersCount;i++) {
				
				if (markers[i] != null) {
				
					markersHTML += "&markers["+i+"][0]="+markers[i].getTitle()+"&markers["+i+"][1]="+markers[i].getPoint()+"&markers["+i+"][2]="+markersText[i];
				
				}
				
			}
			
			
			
		}else{
			markersHTML = "";
		}
		
		//alert(markersHTML);
		
		//get the area_id
		if(document.getElementById("area_id").value != ""){
			area_id = document.getElementById("area_id").value;
			document.getElementById("areaerror").innerHTML = "";
		}else{
			error = true;
			document.getElementById("areaerror").innerHTML = " required";
		}
		
		
		
		routeTitle = document.getElementById("routeTitle").value;
		if(routeTitle == "" || routeTitle == null || routeTitle == "undefined"){
			error = true;
			document.getElementById("titleerror").innerHTML = " required";
		}else{
			document.getElementById("titleerror").innerHTML = "";
		}
		
		routeDescription = document.getElementById("routeDescription").value;
		
		
		client.callback=function(textDocument){
			
			if(textDocument != "false"){

					window.location = "route.php?id="+textDocument;

			}else{
				
				document.getElementById("routeSummary").innerHTML = "Save Failed...";	
			}
			
		}
		
		
		if(error == false){
			//make the request
			client.makeRequest('savemap.php','action=savemap&points='+pointsHTML+'&distance='+distance+'&title='+routeTitle+'&area_id='+area_id+'&distancestring='+this.distanceString+'&description='+routeDescription+markersHTML);
			
			document.getElementById("routeSummary").innerHTML = "<img src='images/loader.gif' alt='saving map' title='please be patient' /><br/>saving map, please be patient";
		}
		
	}
	
}