var map;
var redLED = "http://rush002.com/public/icons/led_red.png";
var greenLED = "http://rush002.com/public/icons/led_green.png";
var event;
var eventID = 105;

var assets = new Array();
var loadCount = 0;
var refreshRate = 600 * 1000; // First number is seconds
var rDilution = 1; // Multiply refresh rate by this number

function load() {
  if (GBrowserIsCompatible()) {
	  
	 var baseIcon = new GIcon();
          baseIcon.iconSize=new GSize(20,20);
          baseIcon.shadowSize=new GSize(56,32);
          baseIcon.iconAnchor=new GPoint(16,32);
          baseIcon.infoWindowAnchor=new GPoint(16,0);
          
      var ny = new GIcon(baseIcon, "http://www.grandadventure08.com/images/1.png", null, null);
      var london   = new GIcon(baseIcon, "http://www.grandadventure08.com/images/2.png", null,null);
       var europe = new GIcon(baseIcon, "http://www.grandadventure08.com/images/3.png", null, null);
	    var russia = new GIcon(baseIcon, "http://www.grandadventure08.com/images/4.png", null, null);
		 var bering = new GIcon(baseIcon, "http://www.grandadventure08.com/images/5.png", null, null);
		  var california = new GIcon(baseIcon, "http://www.grandadventure08.com/images/6.png", null, null);
    
     

      function createOldMarker(point,html,icon) {
        var marker = new GMarker(point,icon);
        GEvent.addListener(marker, "click", function() {
          marker.openInfoWindowHtml(html);
        });
        return marker;
      }  
	  
	  
	  
	map = new GMap2(document.getElementById("map"));
	map.setCenter(new GLatLng(0,0),2, G_PHYSICAL_MAP);
	map.addMapType(G_PHYSICAL_MAP);
	map.addControl(new GScaleControl());
	map.addControl(new GSmallMapControl());
	map.addControl(new GMapTypeControl());
	
	//Check back soon for Live Tracking of the Grand Adventure
		      var point = new GLatLng(40.75,-73.98);
      var marker = createOldMarker(point,'', ny)
      map.addOverlay(marker);

      var point = new GLatLng(51.49,-0.12);
      var marker = createOldMarker(point,'', london)
      map.addOverlay(marker);

      var point = new GLatLng(48.70,13.39);
      var marker = createOldMarker(point,'', europe)
      map.addOverlay(marker);
	  
	        var point = new GLatLng(55.92,86.65);
      var marker = createOldMarker(point,'', russia)
      map.addOverlay(marker);
	  
	        var point = new GLatLng(57.89,-178.69);
      var marker = createOldMarker(point,'', bering)
      map.addOverlay(marker);
	  
	        var point = new GLatLng(37.23,-119.28);
      var marker = createOldMarker(point,'', california)
      map.addOverlay(marker);
	
	// Load the event
	GDownloadUrl("http://rushdb01.com/reconquery.php?eventID="+eventID, function(data, responseCode) {
		var xml = GXml.parse(data);
		loadEvents(xml);
		//Zoom and centre to fit the event
		//map.setCenter(event.bounds.getCenter(),map.getBoundsZoomLevel(event.bounds));
		// Now load the assets
		for (var i in event.ids) {
			var id = event.ids[i];
			GDownloadUrl("http://rushdb01.com/reconquery.php?assetID="+id, function(data, responseCode) {
				var xml = GXml.parse(data);
				loadAssets(xml);
			}) // End asset downloadURL
		}
	}) // End event downloadURL	
  }
}

function refreshAssets(id) {
		var lastreport = assets[id].times[assets[id].times.length-1];
		var url = "http://rushdb01.com/reconquery.php?assetID=" +id+ "&from=" +lastreport;
		GDownloadUrl(url, function(data, responseCode) {
			var xml = GXml.parse(data);
			updateAsset(xml);
			// Set the places
			//setPlaces();
		}) // End downloadURL
}

//Load the xml into event object.
function loadEvents(xml) {
	var eventXML = xml.documentElement.getElementsByTagName("event")[0];
	var id = eventXML.getAttribute("id");
	var name = eventXML.getAttribute("name");
	var starttime = eventXML.getAttribute("start");
	var endtime = eventXML.getAttribute("end");
	var markersXML = eventXML.getElementsByTagName("marker");
	var types = new Array();
	var lats = new Array();
	var lngs = new Array();
	var descs = new Array();
	for (var j = 0; j < markersXML.length; j++) {
		types[j] = markersXML[j].getAttribute("type");
		lats[j] = parseFloat(markersXML[j].getAttribute("lat"));
		lngs[j] = parseFloat(markersXML[j].getAttribute("lng"));
		descs[j] = markersXML[j].getAttribute("desc");
	}
	var idXML = eventXML.getElementsByTagName("eventasset");
	var ids = new Array();
	for (var j = 0; j < idXML.length; j++) {
		ids[j] = idXML[j].getAttribute("id");
	}
	event = new Event(id,name,starttime,endtime,types,lats,lngs,descs,ids);
}

//Load the xml into asset objects.
function loadAssets(xml) {
	var assetXML = xml.documentElement.getElementsByTagName("asset");
	for (var i = 0; i < assetXML.length; i++) {
		var id = assetXML[i].getAttribute("id");
		var name = assetXML[i].getAttribute("name");
		var desc = assetXML[i].getAttribute("desc");
		var colour = assetXML[i].getAttribute("colour");
		var icondata = new Array();
		var iconXML = assetXML[i].getElementsByTagName("icon")[0];
		if (iconXML!=undefined) {
			icondata["url"] = iconXML.getAttribute("url");
			icondata["width"] = parseFloat(iconXML.getAttribute("width"));
			icondata["height"] = parseFloat(iconXML.getAttribute("height"));
			icondata["xanchor"] = parseFloat(iconXML.getAttribute("xanchor"));
			icondata["yanchor"] = parseFloat(iconXML.getAttribute("yanchor"));
		} else { // Set a default icon
			icondata["url"] = "20_green.png";
			icondata["width"] = 12;
			icondata["height"] = 20;
			icondata["xanchor"] = 6;
			icondata["yanchor"] = 20;
		}
		var pointsXML = assetXML[i].getElementsByTagName("p");
		var times = new Array();
		var lats = new Array();
		var lngs = new Array();
		for (var j = 0; j < pointsXML.length; j++) {
			times[j] = pointsXML[j].getAttribute("t");
			lats[j] = parseFloat(pointsXML[j].getAttribute("y"));
			lngs[j] = parseFloat(pointsXML[j].getAttribute("x"));
		}
		assets[id] = new Asset(name,desc,colour,times,lats,lngs,icondata);
		map.addOverlay(assets[id].marker);
		map.addOverlay(assets[id].line);
		map.setCenter(assets[id].centre,assets[id].zoom);
		
		// Set the asset refresh
		//GLog.write("Check "+id+" in "+(Math.round(assets[id].update/6000)/10)+" mins.");
		setTimeout("refreshAssets('"+id+"')", assets[id].update);
	}
}

//Load the uodate xml into existing asset objects.
function updateAsset(xml) {
	var assetXML = xml.documentElement.getElementsByTagName("asset");
	var id = assetXML[0].getAttribute("id");
	var pointsXML = assetXML[0].getElementsByTagName("p");
	var times = new Array();
	var lats = new Array();
	var lngs = new Array();
	if (pointsXML.length > 0) {
		//GLog.write("New position for "+id); 
		for (var j = 0; j < pointsXML.length; j++) {
			times[j] = pointsXML[j].getAttribute("t");
			lats[j] = parseFloat(pointsXML[j].getAttribute("y"));
			lngs[j] = parseFloat(pointsXML[j].getAttribute("x"));
		}
		// Temporarily remove the overlays
		map.removeOverlay(assets[id].marker);
		map.removeOverlay(assets[id].line);
		// Update the asset here
		assets[id].addPoints(times,lats,lngs);
		// Replace the overlays
		map.addOverlay(assets[id].marker);
		map.addOverlay(assets[id].line);
	}		
	map.panTo(assets[id].loc);
	//Refresh the update time
	assets[id].updateTime();
	setTimeout("refreshAssets('"+id+"')", assets[id].update);
}

// This is the event object and constructor
function Event(id,name,starttime,endtime,types,lats,lngs,descs,ids) {
	this.id=id;
	this.ids=ids;
	this.name=name;
	this.starttime=starttime;
	this.endtime=endtime;
	this.startloc = setMarkers(lats,lngs,types,"start",descs);
	this.endloc = setMarkers(lats,lngs,types,"end",descs);
	this.waypoints = setMarkers(lats,lngs,types,"waypoint",descs);
	this.bounds = setBounds(lats,lngs);
	//Private methods for initialising and updating the object
	function setBounds(lats,lngs) {
		var bounds = new GLatLngBounds();
		for (var i in lats) {
			bounds.extend(new GLatLng(lats[i],lngs[i]));
		}
		return bounds;
	}
	function setMarkers(lats,lngs,types,thistype,descs) {
		var newIcon = new GIcon();
		if (thistype=="start") {
			newIcon.image = "";
			newIcon.iconSize = new GSize(12, 20);
			newIcon.iconAnchor = new GPoint(6, 20);
			var title = "Start";
		}
		if (thistype=="end") {
			newIcon.image = "";
			newIcon.iconSize = new GSize(24, 24);
			newIcon.iconAnchor = new GPoint(12, 12);
			var title = "End";
		}
		if (thistype=="waypoint") {
			newIcon.image = "http://rush002.com/public/icons/10_yellow.png";
			newIcon.iconSize = new GSize(24, 24);
			newIcon.iconAnchor = new GPoint(12, 12);
			var title = "Waypoint";
		}
		for (var i=0; i < types.length; i++) {
			if (types[i]==thistype) {
				loc = new GLatLng(lats[i],lngs[i]);
				var assets = new Array();
				var description = descs[i];
				var marker = createMarker(loc, newIcon, title, description);
				map.addOverlay(marker);
				if (thistype=="end")
					return loc;
			} // end if
		} // end for
	} // end setMarker
	
	function createMarker(loc, newIcon, title, description) {
		var marker = new GMarker(loc, {icon:newIcon});
		GEvent.addListener(marker, "mouseover", function() {
			var html = '<img src="'+newIcon.image+'"/> <strong>'+title+'</strong><br>'+description+'<br>';
			Tip(html, BGCOLOR, '#FFF', BORDERCOLOR, '#003E7E', FONTCOLOR, '000', SHADOW, true, FADEIN, 600, FADEOUT, 400);
		});
		GEvent.addListener(marker, "mouseout", function() {
			UnTip();
		});
		GEvent.addListener(marker, "click", function() {
		 	UnTip();
		  	map.panTo(loc);
		});
		return marker;
	}
}

// This is the asset object and constructor
function Asset(name,desc,colour,times,lats,lngs,icondata) {
	this.name=name;
	this.desc=desc;
	this.colour=colour;
	this.times=times;
	this.timestamps=setTimestamps(times);
	this.update=setUpdate(this.timestamps);
	this.lats = lats;
	this.lngs = lngs;
	this.heading = setHeading(this.lats,this.lngs,this.name);
	this.showmarker = false;
	this.showline = false;	
	this.follow = false;
	this.rank = 1;
//	this.heading=heading;
//	this.elev=elev;

	//The following properties are constructed using private methods
	this.loc = setLoc(this.lats,this.lngs);
	this.startLoc = setStartLoc(this.lats,this.lngs);
	this.speeds = setSpeeds(this.lats,this.lngs,this.timestamps);
	this.speed = Math.round(this.speeds[this.speeds.length-1]*1.9438*10)/10;
	this.line = setLine(this.lats,this.lngs,this.colour);
	this.dist = setDist(this.line);
	this.distToEnd = setEndDist(this.loc);
	this.icon = setIcon(icondata);
	this.img = "http://rush002.com/public/icons/" + icondata["url"];
	this.marker = setMarker(this.loc,this.desc,this.timestamps,this.dist,this.icon,this.distToEnd,this.speed);
	this.zoom = setZoom(this.line);
	this.centre = setCentre(this.line);
/*	this.distToStart = Math.round(this.loc.distanceFrom(this.startLoc))/1000;
	this.startTime=startTime;
	this.speed=speed;	
	this.speedAvg
	this.distToLeader = ;
	this.distToDivLeader = ;
	this.estTimeFinish = ;
	this.estTimeCorrectedFinish = ;
	this.standingsMove = ;
*/	
	//Private methods for initialising and updating the object
	function setUpdate(times) {
		
		if (times.length < 3) {
			//GLog.write("Less than 3 reports.");
			return 1200000;
		} else {
			//Calculate the average time in secs for last two reports
			var interval = (times[times.length-1]-times[times.length-3]) / 2;
			//Calculate the time elapsed since last report
			var currentTime = new Date();
			var elapsed = currentTime.getTime() - times[times.length-1];
			var estUpdate = interval - elapsed; // The est time until the next report

			if (estUpdate > 1200000) {
				return 1200000;
			} else if (interval > 1200000) {
				return 1200000;				
			} else if (estUpdate < (-1*interval)) { // double the interval time since last report
				return (interval * rDilution);
			} else if(estUpdate < 0) { // Slightly overdue for a report
				return (0.5*interval * rDilution);
			} else {
				return estUpdate * 1.1 * rDilution; //Add 10% to the estimated update time
			}
		}
	}
	function setTimestamps(timestrings) {
		var stamps = new Array();
		for (var i in timestrings)
			stamps[i] = TimeUTC(timestrings[i]);
		return stamps;
	}
	function setLoc(lats,lngs) {
		var loc = new GLatLng(lats[lats.length-1],lngs[lngs.length-1]);
		return loc;
	}
	function setStartLoc(lats,lngs) {
		var loc = new GLatLng(lats[0],lngs[0]); //First element of lats
		return loc;
	}
	function setSpeeds(lats,lngs,times) {
		var speeds = new Array();
		speeds[0] = 0;
		for (var i=1; i<lats.length; i++) {
			var x = Haversine(lats[i],lngs[i],lats[i-1],lngs[i-1]);
			var t = (times[i]-times[i-1])/1000;
			speeds[i] = x / t;
		}
		return speeds // in m/sec
	}
	function setLine(lats,lngs,colour) {
		if(lats.length<1) {
			lats.push(0);
			lngs.push(0);
		}
		if(lats.length<2) {
			lats.push(lats[0]);
			lngs.push(lngs[0]);
		}
		var latlngs = new Array();
		for (var i in lats)
			latlngs[i] = new GLatLng(lats[i],lngs[i]);
		var encoder = new PolylineEncoder();
		return encoder.dpEncodeToGPolyline(latlngs,colour,4);
	}
	function setZoom(line) {
		var bounds = line.getBounds();
		var zoom = map.getBoundsZoomLevel(bounds);
		return zoom;
	}
	function setCentre(line) {
		var bounds = line.getBounds();
		var centre = bounds.getCenter();
		return centre;
	}
	function setDist(line) {
		return Math.round(line.getLength()*0.53995)/1000;
	}
	function setEndDist(loc) {
		var dist = Math.round(loc.distanceFrom(event.endloc)*0.53995)/1000;
		return dist;
	}
	function setHeading(lats,lngs,name) {
		var lat1 = lats[lats.length-2] * Math.PI / 180;
		var lat2 = lats[lats.length-1] * Math.PI / 180; 		
		var lon1 = lngs[lngs.length-2] * Math.PI / 180;
		var lon2 = lngs[lngs.length-1] * Math.PI / 180; 		
 		var dLon = (lon2-lon1);
		var y = Math.sin(dLon) * Math.cos(lat2);
		var x = Math.cos(lat1)*Math.sin(lat2) - Math.sin(lat1)*Math.cos(lat2)*Math.cos(dLon);
		var heading = Math.atan2(y, x);
		heading = heading * 180 / Math.PI;
		heading = Math.round(((heading)+360) % 360);
		return heading;
	}
	function setIcon(idata) {
		var newIcon = new GIcon();
		newIcon.image = "http://rush002.com/public/icons/" + idata["url"];
		newIcon.iconSize = new GSize(idata["width"], idata["height"]);
		newIcon.iconAnchor = new GPoint(idata["xanchor"], idata["yanchor"]);
		return newIcon;
	}
	function setMarker(loc,desc,timestamps,dist,newicon,distToEnd,speed) {
		var marker = new GMarker(loc, {icon:newicon});
		GEvent.addListener(marker, "mouseover", function() {
			var lastTime = new Date(timestamps[timestamps.length-1]);
			var currentTime = new Date();
			var elapsed = currentTime.getTime() - timestamps[timestamps.length-1];
			if (elapsed > 10800000) {
				var livestatus = '<span class="redtext">Beacon off.</span>';
			} else {
				var livestatus = '<span class="greentext">Live.</span>';
			}				
			var html = '<img class="iconimg" src="'+newicon.image+'" alt="On" /><strong>'+name+'. </strong>'+livestatus+'<br>'+desc+'<br>Lat: '+loc.lat()+', Lng: '+loc.lng()+'<br>'+lastTime+'.'+'<br>Speed: '+speed+' knots.'+'<br>';
			Tip(html, BGCOLOR, '#FFF', BORDERCOLOR, '#003E7E', FONTCOLOR, '000', SHADOW, true, FADEIN, 600, FADEOUT, 400);
		});
		GEvent.addListener(marker, "mouseout", function() {
			UnTip();
		});
		GEvent.addListener(marker, "click", function() {
		 	UnTip();
		  	map.panTo(loc);
		});
		return marker;
	}
	this.updateTime = function () {	
		this.update=setUpdate(this.timestamps);		
	}
	//The following is a public method to add data and update
	this.addPoints = function (nTimes,nLats,nLngs) {
		//Add values to array
		for (var j = 0; j < nTimes.length; j++) {
			this.times.push(nTimes[j]);
			this.timestamps.push(TimeUTC(nTimes[j]));
			this.lats.push(nLats[j]);
			this.lngs.push(nLngs[j]);
		}
		//re-calc properties
		this.loc = setLoc(this.lats,this.lngs);
		this.startLoc = setStartLoc(this.lats,this.lngs);
		this.speeds = setSpeeds(this.lats,this.lngs,this.timestamps);
		this.speed = Math.round(this.speeds[this.speeds.length-1]*1.9438*10)/10;
		this.line = setLine(this.lats,this.lngs,this.colour);
		this.zoom = setZoom(this.line);
		this.centre = setCentre(this.line);
		this.dist = setDist(this.line);
		this.distToEnd = setEndDist(this.loc);
		this.marker = setMarker(this.loc,this.desc,this.timestamps,this.dist,this.icon,this.distToEnd,this.speed);
	}
}

function toggleMarker(thisDiv) {
	//Change the LED and get the new status
	var markerstatus = toggleStatus(thisDiv);
	//Fetch the asset id
	var thisID = thisDiv.parentNode.id;
	if(markerstatus) {
		map.addOverlay(assets[thisID].marker);
		assets[thisID].showmarker = true;
	} else {
		var trackID = "line_"+thisID;
		var trackDiv = document.getElementById(trackID);
		if(checkStatus(trackDiv))
			toggleLine(trackDiv);
		var followID = "follow_"+thisID;
		var followDiv = document.getElementById(followID);
		if(checkStatus(followDiv))
			toggleFollow(followDiv);
		map.removeOverlay(assets[thisID].marker);
		assets[thisID].showmarker = false;
	}
}

function toggleLine(thisDiv) {
	//Change the LED and get the new status
	var trackstatus = toggleStatus(thisDiv);
	//Fetch the asset id, it will be used to turn overlays on/off
	var thisID = thisDiv.parentNode.id;
	if(trackstatus) {
		var markerID = "marker_"+thisID;
		var markerDiv = document.getElementById(markerID);
		if(!checkStatus(markerDiv))
			toggleMarker(markerDiv);
		map.addOverlay(assets[thisID].line);
		assets[thisID].showline = true;
	} else {
		map.removeOverlay(assets[thisID].line);
		assets[thisID].showline = false;
	}
}

function toggleZoom(thisDiv) {
	//Change the LED and get the new status
	//Fetch the asset id, it will be used to turn overlays on/off
	var thisID = thisDiv.parentNode.id;
	map.setCenter(assets[thisID].centre, assets[thisID].zoom);
}

function toggleFollow(thisDiv) {
	//Change the LED and get the new status
	var followstatus = toggleStatus(thisDiv); //Change the follow LED
	//Fetch the asset id, it will be used to turn overlays on/off
	var thisID = thisDiv.parentNode.id;
	if(followstatus) {
		//Check if asset is turned on, if not turn it on.
		var markerID = "marker_"+thisID;
		var markerDiv = document.getElementById(markerID);
		if(!checkStatus(markerDiv))
			toggleMarker(markerDiv);
		//Turn all other autofollows off
		for (var id in assets) {
			if(id != thisID) {
				var followID = "follow_"+id;
				var followDiv = document.getElementById(followID);
				if(checkStatus(followDiv))
					toggleFollow(followDiv);
			}
		}
		//Turn this autofollow on
		assets[thisID].follow = true;
		map.panTo(assets[thisID].loc);
	} else {
		//Turn this autofollow off
		assets[thisID].follow = false;
	}
}

function toggleStatus(thisDiv) {
	var led = thisDiv.getElementsByTagName("img")[0];
	var status = led.className;
	//Change LED to other colour
	if(status=="ledOff") {
		led.src=greenLED;
		led.className="ledOn";
		return true;
	}
	if(status=="ledOn") {
		led.src=redLED;
		led.className="ledOff";
		return false;
	}
}

function checkStatus(thisDiv) {
	var led = thisDiv.getElementsByTagName("img")[0];
	var status = led.className;
	//Return status of the LED
	if(status=="ledOff") {
		return false;
	}
	if(status=="ledOn") {
		return true;
	}
}

function TimeUTC(xString) {
	var xYear = parseFloat(xString.slice(0,4));
	var xMonth = parseFloat(xString.slice(5,7))-1;
	var xDay = parseFloat(xString.slice(8,10));
	var xHour = parseFloat(xString.slice(11,13));
	var xMin = parseFloat(xString.slice(14,16));
	var xSec = parseFloat(xString.slice(17,19));
	return Date.UTC(xYear,xMonth,xDay,xHour,xMin,xSec);
}

function Haversine(lat1, lon1, lat2, lon2) {
  var R = 6371000; // earth's mean radius in metres
  var dLat = (lat2-lat1) *Math.PI/180;
  var dLon = (lon2-lon1) *Math.PI/180;
  lat1 = lat1 *Math.PI/180, lat2 = lat2 *Math.PI/180;

  var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
          Math.cos(lat1) * Math.cos(lat2) * 
          Math.sin(dLon/2) * Math.sin(dLon/2);
  var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
  var d = R * c;
  return d;
}

function setPlaces() {
	for (var id in assets) {
		var ranking = 1;
		var curDist = assets[id].distToEnd;
		//Check curDist against all others
		for (var other in assets) {
			if(curDist > assets[other].distToEnd){
				ranking++;
			}
		}
		
		// Update the place in the standings panel
		assets[id].rank = ranking;
		document.getElementById("place_"+id).innerHTML = assets[id].rank;			
		
		// Update the chart in the standings panel
		/* var d1 = [];
    	for (var i = 0; i < 14; i += 0.5)
        	d1.push([i, Math.sin(i)]);
		$.plot($("#chart_"+id), [ d1 ]);
		*/
	}
}

function createPanel(id) {
		var lastTime = new Date(assets[id].timestamps[assets[id].timestamps.length-1]);
		var currentTime = new Date();
		var elapsed = currentTime.getTime() - lastTime.getTime();
		if (elapsed > 10800000) {
			var livestatus = '<span class="redtext">Beacon off.</span>';
		} else {
			var livestatus = '<span class="greentext">Live.</span>';
		}				
	var newrow=document.createElement('tr');
		newrow.setAttribute('id',id);
		newrow.setAttribute('class','asset');
	var place=document.createElement('td');
		place.setAttribute('id','place_'+id);
		place.setAttribute('class','a_place');
	newrow.appendChild(place);
	var move=document.createElement('td');
		move.setAttribute('class','a_move');
		move.innerHTML = '<img class="ledOff" src="'+assets[id].img+'" alt="Icon" />';
		var html = '<img class="iconimg" src="'+assets[id].img+'"/><strong>'+assets[id].name+'. </strong>'+livestatus+'<br>'+assets[id].desc+'<br>Lat: '+assets[id].loc.lat()+', Lng: '+assets[id].loc.lng()+'<br>'+lastTime+'.'+'<br>Distance travelled: '+assets[id].dist+' km.'+'<br>Distance to end: '+assets[id].distToEnd+' km.<br>';
		move.onmouseover = function () {Tip(html, BGCOLOR, '#FFF', BORDERCOLOR, '#003E7E', FONTCOLOR, '000', SHADOW, true, FADEIN, 600, FADEOUT, 400);};
		move.onmouseout = function () {UnTip();};
	newrow.appendChild(move);
	var label=document.createElement('td');
		label.setAttribute('id','place_'+id);
		label.setAttribute('class','a_label');
		label.innerHTML = '<strong>'+assets[id].name+'</strong><br>'+assets[id].desc;
	newrow.appendChild(label);
	var chart=document.createElement('td');
		chart.setAttribute('id','chart_'+id);
		chart.setAttribute('class','a_chart');
		chart.innerHTML = livestatus;
	newrow.appendChild(chart);
	var spd=document.createElement('td');
		spd.setAttribute('id','spd_'+id);
		spd.setAttribute('class','a_spd');
		spd.innerHTML = assets[id].speed;
	newrow.appendChild(spd);
	var cse=document.createElement('td');
		cse.setAttribute('id','cse_'+id);
		cse.setAttribute('class','a_cse');
		cse.innerHTML = assets[id].heading;
	newrow.appendChild(cse);
	var mark=document.createElement('td');
		mark.setAttribute('id','marker_'+id);
		mark.setAttribute('class','a_marker');
		mark.onclick = function () {toggleMarker(this);};
		mark.innerHTML = '<img class="ledOff" src="'+redLED+'" alt="On" />';	
	newrow.appendChild(mark);	
	var track=document.createElement('td');
		track.setAttribute('id','line_'+id);
		track.setAttribute('class','a_track');
		track.onclick = function () {toggleLine(this);};
		track.innerHTML = '<img class="ledOff" src="'+redLED+'" alt="On" />';	
	newrow.appendChild(track);	
	var zoom=document.createElement('td');
		zoom.setAttribute('id','zoom_'+id);
		zoom.setAttribute('class','a_zoom');
		zoom.onclick = function () {toggleZoom(this);};
		zoom.onmousedown = function () {toggleStatus(this);};
		zoom.onmouseup = function () {toggleStatus(this);};
		zoom.innerHTML = '<img class="ledOff" src="'+redLED+'" alt="On" />';	
	newrow.appendChild(zoom);	
	var follow=document.createElement('td');
		follow.setAttribute('id','follow_'+id);
		follow.setAttribute('class','a_follow');
		follow.onclick = function () {toggleFollow(this);};
		follow.innerHTML = '<img class="ledOff" src="'+redLED+'" alt="On" />';	
	newrow.appendChild(follow);	
	document.getElementById('assetbody').appendChild(newrow);
}


function getColour() {
	var hex = new Array('ff','cc','99','66','33','00');
	do {
		var random = Math.floor(Math.random()*6);
		var red = hex[random];
		var random = Math.floor(Math.random()*6);
		var green = hex[random];
		var random = Math.floor(Math.random()*6);
		var blue = hex[random];
	}
	while ((green==blue) && (red==green)) // Prevent shades of black, white and grey
	
	var colour = "#"+red+green+blue;
	return colour;
}

/**
*
*  Sortable HTML table
*  http://www.webtoolkit.info/
*
**/

function SortableTable (tableEl) {
    this.tbody = tableEl.getElementsByTagName('tbody');
    this.thead = tableEl.getElementsByTagName('thead');
    this.tfoot = tableEl.getElementsByTagName('tfoot');

    this.getInnerText = function (el) {
        if (typeof(el.textContent) != 'undefined') return el.textContent;
        if (typeof(el.innerText) != 'undefined') return el.innerText;
        if (typeof(el.innerHTML) == 'string') return el.innerHTML.replace(/<[^<>]+>/g,'');
    }

    this.getParent = function (el, pTagName) {
        if (el == null) return null;
        else if (el.nodeType == 1 && el.tagName.toLowerCase() == pTagName.toLowerCase())
            return el;
        else
            return this.getParent(el.parentNode, pTagName);
    }

    this.sort = function (cell) {
		var arrowUp = document.createElement("span");
		var tn = document.createTextNode("5");
		arrowUp.appendChild(tn);
		arrowUp.className = "arrow";
	
		var arrowDown = document.createElement("span");
		var tn = document.createTextNode("6");
		arrowDown.appendChild(tn);
		arrowDown.className = "arrow";

        var column = cell.cellIndex;
        var itm = this.getInnerText(this.tbody[0].rows[1].cells[column]);
        var sortfn = this.sortCaseInsensitive;

        if (itm.match(/\d\d[-]+\d\d[-]+\d\d\d\d/)) sortfn = this.sortDate; // date format mm-dd-yyyy
        if (itm.replace(/^\s+|\s+$/g,"").match(/^[\d\.]+$/)) sortfn = this.sortNumeric;

        this.sortColumnIndex = column;

        var newRows = new Array();
        for (j = 0; j < this.tbody[0].rows.length; j++) {
            newRows[j] = this.tbody[0].rows[j];
        }

        newRows.sort(sortfn);
        
		var sortCells = cell.parentNode.childNodes;
        for (var j in sortCells) {
	        for (var i in sortCells[j].childNodes) {
	        	if (sortCells[j].childNodes[i].className == "arrow")
	        		sortCells[j].removeChild(sortCells[j].childNodes[i]);
	        }
        }

        if (cell.getAttribute("sortdir") == 'down') {
            newRows.reverse();
            cell.setAttribute('sortdir','up');
            cell.appendChild(arrowUp);            
        } else {
            cell.setAttribute('sortdir','down');
            cell.appendChild(arrowDown);
        }

        for (i=0;i<newRows.length;i++) {
            this.tbody[0].appendChild(newRows[i]);
        }

    }

    this.sortCaseInsensitive = function(a,b) {
        aa = thisObject.getInnerText(a.cells[thisObject.sortColumnIndex]).toLowerCase();
        bb = thisObject.getInnerText(b.cells[thisObject.sortColumnIndex]).toLowerCase();
        if (aa==bb) return 0;
        if (aa<bb) return -1;
        return 1;
    }

    this.sortDate = function(a,b) {
        aa = thisObject.getInnerText(a.cells[thisObject.sortColumnIndex]);
        bb = thisObject.getInnerText(b.cells[thisObject.sortColumnIndex]);
        date1 = aa.substr(6,4)+aa.substr(3,2)+aa.substr(0,2);
        date2 = bb.substr(6,4)+bb.substr(3,2)+bb.substr(0,2);
        if (date1==date2) return 0;
        if (date1<date2) return -1;
        return 1;
    }

    this.sortNumeric = function(a,b) {
        aa = parseFloat(thisObject.getInnerText(a.cells[thisObject.sortColumnIndex]));
        if (isNaN(aa)) aa = 0;
        bb = parseFloat(thisObject.getInnerText(b.cells[thisObject.sortColumnIndex]));
        if (isNaN(bb)) bb = 0;
        return aa-bb;
    }

    // define variables
    var thisObject = this;
    var sortSection = this.thead;

    // constructor actions
    if (!(this.tbody && this.tbody[0].rows && this.tbody[0].rows.length > 0)) return;

    if (sortSection && sortSection[0].rows && sortSection[0].rows.length > 0) {
        var sortRow = sortSection[0].rows[0];
    } else {
        return;
    }

    for (var i=0; i<sortRow.cells.length; i++) {
        sortRow.cells[i].sTable = this;
        sortRow.cells[i].onclick = function () {
            this.sTable.sort(this);
            return false;
        }
    }
    sortRow.cells[0].sTable.sort(sortRow.cells[0]);
}