////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// static
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

var session = ''
var user_id = ''
//var urlPrefix
var tracks   		= new Array()
var track_displayed = 0
var loading_track_busy = false
var loading_track_busy_index = -1
var click_handle = 0
var global_counter = 0
var number_selected
var global_scratch
var exporting = false
var exportingGPX = false


function showTracks()
{
	var scratch = '<b>Select a track to show</b>' 
	scratch += '<SELECT NAME=list_tracks id="list_tracks" SIZE = 10 MULTIPLE onChange="onShowTrack()" style="overflow: hidden; width: 190; white-space : nowrap; font-size:11px;line-height: 11px; margin-bottom: 0px; margin-top: 0px; ">'
	var i
	for (i = 0; i < tracks.length; i++)
	{
		scratch += '<OPTION> ' + tracks[i].getName()
	}
	scratch += '</SELECT>'
	scratch += '<BR>'
  	scratch += '<br>'	
	document.getElementById('divMyTracks').innerHTML = scratch
	showControls()
}

function showControls()
{
	scratch = '<table ><tr>'
	scratch += '<td><INPUT NAME=RenameTracks   TYPE=button   VALUE="Rename" onClick="onRenameTrack()"  TITLE="Rename selected track, please select one track only">'
	scratch += '<INPUT NAME=DeleteTracks   TYPE=button   VALUE="Del" onClick="onDeleteTracks()"  TITLE="Delete selected tracks"></td>'
	scratch += '</tr>'
	scratch += '<tr>'
	scratch += '<td><INPUT NAME=ExportCurrentTrack   TYPE=button   VALUE="Export Excel" onClick="onExportTracks()"  TITLE="Export selected tracks to a tab separated file that can be read by for example Excel"></td>'
	scratch += '</tr>'
	scratch += '<tr>'
	scratch += '<td><INPUT NAME=ExportCurrentTrackGPX   TYPE=button   VALUE="Export GPX" onClick="onExportTracksGPX()"  TITLE="Export selected tracks to a GPX file"></td>'
	scratch += '</tr></table>'
	document.getElementById('divMyTracksControls').innerHTML = scratch	
}

function onShowTrack()
{
	if (loading_track_busy != true)
	{
		var path1 = document.getElementById('list_tracks')		
		var ns = 0
		for (var i = 0; i < path1.options.length; i++)
		{
			if (path1.options[i].selected)
	    	{
				ns++
				loading_track_busy_index = i
	    	}			
		}
		if (ns == 1)
		{
			loading_track_busy=true
			removeDisplayedTrack()
			tracks[loading_track_busy_index].addToDisplayedTracks()
		}
	}
	else
	{
		setTimeout(onShowTrack, 250)
		
	}
}


function removeDisplayedTrack()
{
	if (track_displayed != 0)
	{
		map.removeOverlay(track_displayed.trackoverlay)
		map.closeInfoWindow()
	}
	track_displayed = 0
}

function disableMyTracks()
{
	removeDisplayedTrack()
	if (click_handle != 0)
	{
		GEvent.removeListener(click_handle)
	}
	click_handle = 0
}

function onExportTracks()
{
	var index = computeNumberSelected()
	if (number_selected == 0)
	{
		alert('Select one or more tracks')
		return
	}
	if (loading_track_busy != true)
	{
		
		var confirm1 = confirm("Do you really want to export the selected tracks?");
		if (confirm1 == true)
		{
			removeDisplayedTrack()
			global_counter = 0
			exporting = true	

			global_scratch = 'Track report<br>Copy/paste this window to Excel<br><br>'
			global_scratch += '<table><tr><td>Name</td><td>Start</td><td>End</td><td>From</td><td>To</td><td>Distance km</td><td>Av Speed km/h</td><td>Max Speed km/h</td><td>Distance mi</td><td>Av Speed mi/h</td><td>Max Speed mi/h</td></tr>'				
			var path1 = document.getElementById('list_tracks')		
			loading_track_busy_index = -1
			loading_track_busy = true
			nextExport()
		}	
	}
	else
	{
		setTimeout(onExportTracks, 250)
	}
}

function onExportTracksGPX()
{
	var index = computeNumberSelected()
	if (number_selected == 0)
	{
		alert('Select one or more tracks')
		return
	}
	if (loading_track_busy != true)
	{
		
		var confirm1 = confirm("Do you really want to export the selected tracks?");
		if (confirm1 == true)
		{
			removeDisplayedTrack()
			global_counter = 0
			exportingGPX = true
			var d = new Date()
			

			global_scratch = '&#60;gpx version="1.0" creator="Trackthisout - http://www.trackthisout.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.topografix.com/GPX/1/0" xmlns:topografix="http://www.topografix.com/GPX/Private/TopoGrafix/0/2" xsi:schemaLocation="http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd http://www.topografix.com/GPX/Private/TopoGrafix/0/2 http://www.topografix.com/GPX/Private/TopoGrafix/0/2/topografix.xsd"&#62;<br>'
			global_scratch += '&#60;time&#62;' + d.formatUTC('yyyy-mm-ddThh:nn:ssZ') + '&#60;/time&#62;<br>'
			
			var path1 = document.getElementById('list_tracks')		
			loading_track_busy_index = -1
			loading_track_busy = true
			nextExportGPX()
		}	
	}
	else
	{
		setTimeout(onExportTracksGPX, 250)
	}
}

function nextExportGPX()
{
	var path1 = document.getElementById('list_tracks')		
	loading_track_busy_index++
	global_counter++
	var n = path1.options.length
	for (var i = loading_track_busy_index; i < n; i++)
	{
		if (path1.options[i].selected)
    	{
			loading_track_busy_index = i
			tracks[loading_track_busy_index].loadTrack() // this is loading or exporting
			return
    	}			
	}
	loading_track_busy=false
	exportingGPX = false
	document.getElementById('divMyTracksInfo').innerHTML = ''
	var myTempWindow = window.open('','cont',"toolbar=yes,menubar=yes, scrollbars=yes");
	myTempWindow.focus()
	global_scratch += '&#60;/gpx&#62;</body></html>\n'
	myTempWindow.document.write(global_scratch)
}

function nextExport()
{
	var path1 = document.getElementById('list_tracks')		
	loading_track_busy_index++
	global_counter++
	var n = path1.options.length
	for (var i = loading_track_busy_index; i < n; i++)
	{
		if (path1.options[i].selected)
    	{
			loading_track_busy_index = i
			tracks[loading_track_busy_index].loadTrack() // this is loading or exporting
			return
    	}			
	}
	loading_track_busy=false
	exporting = false
	document.getElementById('divMyTracksInfo').innerHTML = ''
	var myTempWindow = window.open('','cont',"toolbar=yes,menubar=yes, scrollbars=yes");
	myTempWindow.focus()
	global_scratch += '</table>'
	myTempWindow.document.write(global_scratch)
}

function deleteNextTrack()
{
	var path1 = document.getElementById('list_tracks')		
	loading_track_busy_index--
	global_counter++
	for (var i = loading_track_busy_index; i >= 0; i--)
	{
		if (path1.options[i].selected)
    	{
			loading_track_busy_index = i			
			document.getElementById('divMyTracksInfo').innerHTML = '<p>Deleting track ' + global_counter + '/' + number_selected + '</p>'
			path1.remove(i)
			tracks[i].deleteTrack()
			tracks.splice(i, 1)
			return
    	}			
	}
	loading_track_busy=false
	document.getElementById('divMyTracksInfo').innerHTML = ''
}

function onDeleteTracks()
{
	computeNumberSelected()
	if (number_selected == 0)
	{
		alert('Select one or more tracks')
		return
	}
	if (loading_track_busy != true)
	{
		var confirm1 = confirm("Do you really want to delete the selected tracks?");
		if (confirm1 == true)
		{
			global_counter = 0
			removeDisplayedTrack()
			var path1 = document.getElementById('list_tracks')		
			loading_track_busy_index = path1.options.length
			loading_track_busy = true			
			deleteNextTrack()
		}
	}
	else
	{
		setTimeout(onDeleteTracks, 250)		
	}
}

function computeNumberSelected()
{
	var index_selected = -1
	number_selected = 0;
	var path1 = document.getElementById('list_tracks')		
	var n = path1.options.length
	for (var i = 0; i < n; i++)
	{
		if (path1.options[i].selected)
    	{
    		index_selected = i;
    		number_selected++;
    	}			
	}	
	return index_selected;
}

function onRenameTrack()
{
	if (loading_track_busy != true)
	{
		var index = computeNumberSelected()
		if (number_selected == 1)
		{
			   loading_track_busy = true;
			   var scratch = '';
			   scratch += '			<p class="narrow">New name:</p>'
			   scratch += '			<INPUT NAME=new_name id="new_name" TYPE=text SIZE=20>'
			   scratch += '		<table>'
			   scratch += '		<tr>'
			   scratch += '			<td><INPUT NAME=Rename        TYPE=button VALUE="Rename" onClick="OnRename()"  ></td>'
			   scratch += '			<td><INPUT NAME=CancelRename  TYPE=button VALUE="Cancel" onClick="OnCancelRename()"  ></td>'
			   scratch += '		</tr>'
			   scratch += '		</table>'
				document.getElementById('divMyTracksControls').innerHTML = scratch	
		}
		else
		{
			alert('Select exactly one track')
		}
	}
	else
	{
		setTimeout(onRenameTrack, 250)
	}
}

function OnCancelRename()
{
	loading_track_busy = false;
	showControls()
}

function OnRename()
{
	var nn = document.frmMyTracks.elements['new_name'].value;
	tracks[loading_track_busy_index].rename(nn)
	var path1 = document.getElementById('list_tracks')		
	path1.options[loading_track_busy_index].text = nn
	document.getElementById('divMyTracksControls').innerHTML = 'renaming...'
}

function getTracks()
{
	document.getElementById('divMyTracks').innerHTML = "loading tracks...";
	GDownloadUrl(urlPrefix + "/online/os.asp?a=lt&i=" + escape(user_id) + "&s=" + escape(session),
		function (data, responseCode)
		{
			var xmlDoc = GXml.parse(data);
			if ("result" == xmlDoc.documentElement.nodeName)
			{
				var tmLastError = parseInt(xmlDoc.documentElement.getAttribute("id"))
				checkError(tmLastError);
				showLogin();
			}
			else
			{
				var tracksxml = xmlDoc.documentElement.getElementsByTagName("info_track");
				for (var i = 0; i < tracksxml.length; i++)
				{
					try
					{
						var t = new Track(tracksxml[i]);
						tracks.push(t)
					}
					catch(err){alert("err=" + err)}
				}					
			}			
			showTracks()
		}
	)
}

function drawFrameMyTracks()
{
	if (click_handle == 0)
	{
		click_handle = GEvent.addListener(map, 'click', function(overlay, point)	// Add a click listener
	     {
	      clickHandler(point)
	     });
	}
	
	if (session == '')
	{
		showLogin();
	}
	else
	{
		if (tracks.length == 0)
		{
			getTracks()
		}
		showTracks()
	}
}

// Show nearest point (if closer than 5000m)
function clickHandler(point)
{
	if (loading_track_busy == false)
	{
		// find closest point
		var ti = 0
		var pi = 0
		var min_dist_metres = 50000
		var min_ti = -1
		var min_pi = -1
		if (track_displayed != 0)
		{
			var t = track_displayed
			for (pi = 0; pi < t.positions.length; pi++)
			{
				var d = point.distanceFrom(t.positions[pi])
				if (d < min_dist_metres)
				{
					min_dist_metres = d
					min_ti = ti
					min_pi = pi
				}
			}
			if (min_ti >= 0)
			{
				t.showPoint(min_pi)
			}
		}
	}
}

function showLogin()
{

   var scratch = '';
   scratch += '		<br>'
   scratch += '		<table BORDER=0 CELLPADDING=3 CELLSPACING=0>'
   scratch += '		<tr>'
   scratch += '			<td>'
   scratch += '			<p class="narrow">email address:</p>'
   scratch += '			<INPUT NAME=Email_address TYPE=text SIZE=27>'
   scratch += '			</td>'
   scratch += '		</tr>'
   scratch += '		<tr>'
   scratch += '			<td>'
   scratch += '			<p class="narrow">password:</p>'
   scratch += '			<INPUT NAME=Password TYPE=password SIZE=27>'
   scratch += '			</td>'
   scratch += '		</tr>'
   scratch += '		<tr><td>'
   scratch += '			<INPUT NAME=Login  TYPE=button VALUE="Login" onClick="OnLoggingIn()"  >'
   scratch += '		</td></tr>'
   scratch += '		</table>'
   document.getElementById('divMyTracks').innerHTML = scratch
}

function OnLoggingIn()
{
	try 
	{
		netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
		netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
	} 
	catch (e) 
	{
	}
	var email = document.frmMyTracks.elements['Email_address'].value;
	var pwd = document.frmMyTracks.elements['Password'].value;
	// hack
	//email = "b14@freeler.nl"
	//pwd="test"
	// postfix URL with current date/time so prevent cached results for this request
	
	GDownloadUrl(urlPrefix + "/online/os.asp?a=ul&e=" + escape(email) + "&p=" + escape(pwd) + "&d=PC&q=" + escape(Date()),
		function (data, responseCode)
		{
			var xmlDoc = GXml.parse(data);
			if ("result" == xmlDoc.documentElement.nodeName)
			{
				// expected error codes: 5, 7, 8, or 9
				var tmLastError = parseInt(xmlDoc.documentElement.getAttribute("id"))
				checkError(tmLastError);
			}
			else
			{
				session = xmlDoc.getElementsByTagName('session')[0].firstChild.nodeValue;
				user_id = xmlDoc.getElementsByTagName('user')[0].getAttribute("id");

				if (user_id == null || session == null)
				{
					session = '';
					alert("Log in failed, probably server down");					
				}
				else
				{
					getTracks();
				}
			}
		}
	)
}

function checkError(error)
{
	
	switch (error)
	{
		case 0: break;
		case 1:  alert('Email format not correct .'); break;
		case 3:  alert('Password format not correct .'); break;
		case 4:  alert('Password not correct .'); break;
		case 5 : alert('The nickname you entered may not be empty.\n\nEnter exactly the same nickname as specified in Tracky.'); break;
		case 7 : alert('Nickname does not exist.\n\n1) enter exactly the same nickname as specified in Tracky\n2) make sure the client you try to track uses Tracky version 2.2 or higher'); break;
		case 8 : alert('Enter a valid PIN code.'); break;
		case 9 : alert('The PIN code you entered does not match the PIN code as specified in Tracky.'); break;
		case 11 : alert('User id not known'); break;
		case 12 : alert('Email not known'); break;
		case 13 : alert('Invalid session'); break;
		case 14 : alert('User banned'); break;
		default: alert('unknown error (' + error + ')'); break;
	}
	
}

// is called with a placemark if the reverse geocode request was successfull
// sets the result div
function goodresult(placemark) 
{  
  var that = tracks[loading_track_busy_index]
  that.addToDisplayedTracks3(placemark.address)

}

// is called if the reverse geocode request was unsuccessfull
function badresult() 
{
  var that = tracks[loading_track_busy_index]
  that.addToDisplayedTracks3('unknown')
}

// is called with a placemark if the reverse geocode request was successfull
// sets the result div
function goodresult4(placemark) 
{  
  var that = tracks[loading_track_busy_index]
  that.addToDisplayedTracks4(placemark.address)

}

// is called if the reverse geocode request was unsuccessfull
function badresult4() 
{
  var that = tracks[loading_track_busy_index]
  that.addToDisplayedTracks4('unknown')
}

// is called with a placemark if the reverse geocode request was successfull
// sets the result div
function goodresultsp(placemark) 
{  
  track_displayed.showPoint2(placemark.address)
}

// is called if the reverse geocode request was unsuccessfull
function badresultsp() 
{
  track_displayed.showPoint2('unknown')
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// class
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

function Track(xml)
{
	this.id = parseInt(xml.getAttribute('id'))
		
	this.positions = new Array()
	this.dates = new Array()
	this.trackoverlay = 0
	this.current = 0
	this.getName = Track_getName;
	this.loadTrack = Track_loadTrack;
	//this.unloadTrack = Track_unloadTrack;
	this.loadTrackCore = Track_loadTrackCore
	this.export2 = Track_export2
	this.exportGPX2 =  Track_exportGPX2
	this.addToDisplayedTracks = Track_addToDisplayedTracks
	this.addToDisplayedTracks2 = Track_addToDisplayedTracks2
	this.addToDisplayedTracks3 = Track_addToDisplayedTracks3
	this.addToDisplayedTracks4 = Track_addToDisplayedTracks4
	this.fillTrackInfoString = Track_fillTrackInfoString
	this.deleteTrack = Track_deleteTrack
	this.showNiceOnGoogleMaps = Track_showNiceOnGoogleMaps
	this.rename = Track_rename
	this.showPoint = Track_showPoint
	this.showPoint2 = Track_showPoint2
	this.showPointCore = Track_showPointCore
	this.current_point_index
	this.getSpeedOfPoint = Track_getSpeedOfPoint
	this.getDeltaTime = Track_getDeltaTime
	this.name = ""
	this.firstdate
	this.loaded = false
	this.address = ''
	
	this.from = 'loading...'
	this.to = 'loading...'
	
	this.av_speed
	this.max_speed
	this.distance
	
	for (var i = 0; i < xml.childNodes.length; i++)
	{
		if (xml.childNodes[i].firstChild)
		{
			var name1 = xml.childNodes[i].nodeName
			var val  = xml.childNodes[i].firstChild.nodeValue
			if (name1 == "name")
			{
				this.name = val
			}
			else if (name1 == "date")
			{
				var d = new Date(val + " MST");
				this.firstdate = d
				var month = d.getMonth() + 1
			  	//this.date = d.getDate() + '/' + month + '/' + d.getFullYear() + ' ' + d.getHours() + ':' + d.getMinutes()
			  	this.date = d.format('hh:nn:ss mm/dd/yyyy ddd')
			}
		}
	}
	if (this.name.length < 1)
	{
		this.name = this.name + " " + this.date;
	}
}

function Track_rename(new_name)
{
	this.name = new_name
	GDownloadUrl(urlPrefix + "/online/os.asp?a=rti&i=" + escape(user_id) + "&s=" + escape(session) + "&t=" + this.id + "&n=" + escape(new_name),
		function (data, responseCode)
		{	
			var xmlDoc = GXml.parse(data);
			if ("result" == xmlDoc.documentElement.nodeName)
			{
				var tmLastError = parseInt(xmlDoc.documentElement.getAttribute("id"))
				checkError(tmLastError);				
			}
			loading_track_busy = false
			showControls()
			tracks[loading_track_busy_index].fillTrackInfoString()
		}
	)
}

function Track_deleteTrack()
{
	GDownloadUrl(urlPrefix + "/online/os.asp?a=dti&i=" + escape(user_id) + "&s=" + escape(session) + "&t=" + this.id,
		function (data, responseCode)
		{	
			var xmlDoc = GXml.parse(data);
			if ("result" == xmlDoc.documentElement.nodeName)
			{
				var tmLastError = parseInt(xmlDoc.documentElement.getAttribute("id"))
				checkError(tmLastError);				
			}
			deleteNextTrack()
		}
	)
}

function Track_loadTrackCore(data)
{
	this.max_speed = 0
	this.distance = 0
	this.av_speed = 0
	var xmlDoc = GXml.parse(data);
	if ("result" == xmlDoc.documentElement.nodeName)
	{
		var tmLastError = parseInt(xmlDoc.documentElement.getAttribute("id"))
		checkError(tmLastError);				
	}
	else
	{
		var pointsxml = xmlDoc.documentElement.getElementsByTagName("waypoint");
		for (var i = 0; i < pointsxml.length; i++)
		{
			var x = 0
			var y = 0
			var datet = 0
			for (var j = 0; j < pointsxml[i].childNodes.length; j++)
			{
				if (pointsxml[i].childNodes[j].firstChild)
				{
					var name1 = pointsxml[i].childNodes[j].nodeName
					var val  = pointsxml[i].childNodes[j].firstChild.nodeValue
					if (name1 == "x")
					{
						x = val
					}
					else if (name1 == "y")
					{
						y = val
					}
					else if (name1 == "date")
					{
						datet = new Date(val + " MST");
					  	
					}
				}
			}
			if (x != 0 && y != 0)
			{						
				this.dates.push(datet)	
				this.positions.push(new GLatLng(y, x))
				
				// compute distance, max_speed
				var i1 = this.positions.length - 1
				if (i1 > 0)
				{							
					var p2 = this.positions[i1]
					var p1 = this.positions[i1 - 1]
					var d = p2.distanceFrom(p1) / 1000
					var s = (d / this.getDeltaTime(i1, i1-1))
												
					if (s > this.max_speed) this.max_speed = s
					this.distance += d
				}						
			}
		}	
	}		
	var i2 = this.positions.length - 1
	if (i2 > 0)
	{
		this.av_speed = this.distance / this.getDeltaTime(i2, 0)
	}	
}

function Track_export2()
{
	if (this.positions.length != 0)
	{
		var fromurl = "http://www.trackthisout.com/tm.html?lat=" + (this.positions[0].lat())     + "&lng=" + parseFloat(this.positions[0].lng())
		var tourl   = "http://www.trackthisout.com/tm.html?lat=" + (this.positions.last().lat()) + "&lng=" + parseFloat(this.positions.last().lng())
		global_scratch += '<tr><td>' + this.name + '</td>' 
		global_scratch += '<td>' + this.firstdate.format('hh:nn:ss mm/dd/yyyy ddd') + '</td>'
		global_scratch += '<td>' + this.dates.last().format('hh:nn:ss mm/dd/yyyy ddd') + '</td>'
		global_scratch += '<td><a href="' + fromurl + '">' + this.from + '</a></td>'
		global_scratch += '<td><a href="' + tourl + '">' + this.to + '</a></td>'
		var d = ('' + this.distance).substring(0, 5)
		var d2 = ('' + this.distance * 0.621118).substring(0, 5)
		var s1 = ('' + this.av_speed).substring(0, 5)
		var s2 = ('' + (this.av_speed* 0.621118)).substring(0, 5)
		var ms1 = ('' + this.max_speed).substring(0, 5)
		var	ms2 = ('' + (this.max_speed* 0.621118)).substring(0, 5)
		global_scratch += '<td>' + d + '</td>'
		global_scratch += '<td>' + s1 + '</td>'
		global_scratch += '<td>' + ms1 + '</td>'
		global_scratch += '<td>' + d2 + '</td>'
		global_scratch += '<td>' + s2 + '</td>'
		global_scratch += '<td>' + ms2 + '</td></tr>'
		if (!this.loaded)
		{
			this.dates = new Array()
			this.positions = new Array()		
		}
	}
	else
	{
		global_scratch += '<tr><td>' + this.name + '</td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>'				
	}
	nextExport()
}

function Track_exportGPX2()
{
	if (this.positions.length != 0)
	{
		global_scratch += '&#60;trk&#62;<br>'
		global_scratch += '&#60;name&#62;' + this.getName() + '&#60;/name&#62;<br>'
		global_scratch += '&#60;trkseg&#62;<br>'
		
		for (var i = 0; i < this.positions.length; i++)
		{
			global_scratch += '&#60;trkpt lat="' + (this.positions[i].lat()) + '" lon="' + parseFloat(this.positions[i].lng()) + '"&#62;' + 
			   '&#60;time&#62;' + this.dates[i].formatUTC('yyyy-mm-ddThh:nn:ssZ') + '&#60;/time&#62;&#60;/trkpt&#62;<br>'
		}
				
		global_scratch += '&#60;/trkseg&#62;<br>'
		global_scratch += '&#60;/trk&#62;<br>'
	}
	
	nextExportGPX()
}

function Track_loadTrack()
{
	if (exporting)
	{
		document.getElementById('divMyTracksInfo').innerHTML = '<p>Exporting: ' + global_counter + '/' + number_selected + '</p>'		
		if (this.loaded)
		{
			this.export2()
			return
		}
	}
	else if (exportingGPX)
	{
		document.getElementById('divMyTracksInfo').innerHTML = '<p>Exporting: ' + global_counter + '/' + number_selected + '</p>'		
		if (this.loaded)
		{
			this.exportGPX2()
			return
		}
	}
	else
	{
		document.getElementById('divMyTracksInfo').innerHTML = '<p>Loading track...</p>'		
	}
	GDownloadUrl(urlPrefix + "/online/os.asp?a=bpi&i=" + escape(user_id) + "&s=" + escape(session) + "&t=" + this.id,
		function (data, responseCode)
		{	
			var that = tracks[loading_track_busy_index]
			that.loadTrackCore(data)		
			that.addToDisplayedTracks2()		
		}
	)
	
}

function Track_fillTrackInfoString()
{
	if (this.positions.length == 0)
	{
		scratch = 'Empty track<br><br>'
	}
	else
	{
		//load info block
		var scratch = '<b>Track Info</b><br>'
		scratch += '<p class="narrow">'
		scratch += '<table>'
		scratch += '<tr><td bgcolor=#F8F8FF style="overflow: hidden; width: 190; white-space : font-size:11px;line-height: 11px; margin-bottom: 0px; margin-top: 0px; ">'
		scratch += '<b>Name:</b><br>' + this.getName() + '<br>'
		scratch += '</td></p></tr>'			
	
		scratch += '<tr><td bgcolor=#F8F8FF style="overflow: hidden; width: 190; white-space : font-size:11px;line-height: 11px; margin-bottom: 0px; margin-top: 0px; ">'
		scratch += '<b>Start:</b><br>' + this.firstdate.format('hh:nn:ss mm/dd/yyyy ddd') + '<br>'
		scratch += '</td></p></tr>'			
	
		
		scratch += '<tr><td bgcolor=#F8F8FF style="overflow: hidden; width: 190; white-space : font-size:11px;line-height: 11px; margin-bottom: 0px; margin-top: 0px; ">'
		scratch += '<b>End:</b><br>' + this.dates.last().format('hh:nn:ss mm/dd/yyyy ddd')  + '<br>'
		scratch += '</td></p></tr>'			
	
		var d = ('' + this.distance).substring(0, 5)
		var d2 = ('' + this.distance * 0.621118).substring(0, 5)
		scratch += '<tr><td bgcolor=#F8F8FF style="overflow: hidden; width: 190; white-space : font-size:11px;line-height: 11px; margin-bottom: 0px; margin-top: 0px; ">'
		scratch += '<b>Distance:</b><br>' + d + ' km, ' + d2  + ' mi<br>'
		scratch += '</td></p></tr>'			
		
		var s1 = ('' + this.av_speed).substring(0, 5)
		var s2 = ('' + (this.av_speed* 0.621118)).substring(0, 5)
		scratch += '<tr><td bgcolor=#F8F8FF style="overflow: hidden; width: 190; white-space : font-size:11px;line-height: 11px; margin-bottom: 0px; margin-top: 0px; ">'
		scratch += '<b>Average speed:</b><br>' + s1 + ' km/h, ' + s2  + ' mi/h<br>'
		scratch += '</td></p></tr>'			
		
		s1 = ('' + this.max_speed).substring(0, 5)
		s2 = ('' + (this.max_speed* 0.621118)).substring(0, 5)
		scratch += '<tr><td bgcolor=#F8F8FF style="overflow: hidden; width: 190; white-space : font-size:11px;line-height: 11px; margin-bottom: 0px; margin-top: 0px; ">'
		scratch += '<b>Max speed:</b><br>' + s1 + ' km/h, ' + s2  + ' mi/h<br>'
		scratch += '</td></p></tr>'			
	
		scratch += '<tr><td bgcolor=#F8F8FF style="overflow: hidden; width: 190; white-space : font-size:11px;line-height: 11px; margin-bottom: 0px; margin-top: 0px; ">'
		scratch += '<b>From:</b><br>' + this.from + '<br>'
		scratch += '</td></p></tr>'			
	
		scratch += '<tr><td bgcolor=#F8F8FF style="overflow: hidden; width: 190; white-space : font-size:11px;line-height: 11px; margin-bottom: 0px; margin-top: 0px; ">'
		scratch += '<b>To:</b><br>' + this.to + '<br>'
		scratch += '</td></p></tr>'			
	
		scratch += '</table>'
		scratch += '</p>'
		scratch += '<br><b>Tip:</b> Click a point on the track<br><br>'
	}
	document.getElementById('divMyTracksInfo').innerHTML = scratch
}

function Track_addToDisplayedTracks2()
{
	// add to overlay
	if (this.positions.length == 0)
	{
		this.loaded = true
		if (exporting) 
		{
			this.export2()
			return
		}
		if (exportingGPX)
		{
			this.exportGPX2()
			return
		}
		this.fillTrackInfoString()
		loading_track_busy = false		
	}
	else
	{
		if (!(exporting || exportingGPX))
		{
			track_displayed = this		
			this.trackoverlay = new GPolyline(this.positions, "#0000FF", 5, 0.5)
			map.addOverlay(this.trackoverlay)
			this.fillTrackInfoString()
			this.showNiceOnGoogleMaps()		
		}
		// get from
		rg = new GReverseGeocoder(map);
		GEvent.addListener(rg, "load", goodresult);
		GEvent.addListener(rg, "error", badresult);
		rg.reverseGeocode(this.positions[0]);
	}
}

function Track_showNiceOnGoogleMaps()
{
	if (this.positions.length == 0) return
	var bbox = this.trackoverlay.getBounds()
	var z = map.getBoundsZoomLevel(bbox) 
	map.setCenter(bbox.getCenter())
	map.setZoom(z)
	
	return
	var p1 = this.positions[0]
	var p2 =  this.positions.last()
	var lat1 = (p1.lat() + p2.lat()) / 2
	
	var xlng1 = (parseFloat(p1.lng()) + parseFloat(p2.lng())) / 2
	map.setCenter(new GLatLng(lat1  , xlng1 ))
	gp1 = map.fromLatLngToDivPixel(p1)
	gp2 = map.fromLatLngToDivPixel(p2)
	while(gp1.x < 0 || gp1.x > 721 ||
	      gp2.x < 0 || gp2.x > 721 ||
	      gp1.y < 0 || gp1.y > 500 ||
	      gp2.y < 0 || gp2.y > 500)
	{
		map.zoomOut()
		gp1 = map.fromLatLngToDivPixel(p1)
		gp2 = map.fromLatLngToDivPixel(p2)		
	}
}

function Track_addToDisplayedTracks3(from)
{
	this.from = from
	if (!exporting || !exportingGPX) this.fillTrackInfoString()
	
	// get to
	
	rg = new GReverseGeocoder(map);
	GEvent.addListener(rg, "load", goodresult4);
	GEvent.addListener(rg, "error", badresult4);
	rg.reverseGeocode(this.positions.last());
	
}

function Track_addToDisplayedTracks4(to)
{
	this.to = to
	if (exporting)
	{
		this.export2()
	}
	else if (exportingGPX)
	{
		this.exportGPX2()
	}
	else
	{
		loading_track_busy = false
		this.loaded = true
		this.fillTrackInfoString()
	}
}

function Track_addToDisplayedTracks()
{
	if (this.loaded == false)
	{
		this.loadTrack()
	}
	else
	{
		this.fillTrackInfoString()
		this.trackoverlay = new GPolyline(this.positions, "#0000FF", 5, 0.5)
		map.addOverlay(this.trackoverlay)
		track_displayed = this
		this.showNiceOnGoogleMaps()
		loading_track_busy = false
	}	
}

function Track_getName()
{
	return this.name
}

// returns speed in km/h of point i
function Track_getSpeedOfPoint(i)
{
	if (i < 1) return 0
	var p2 = this.positions[i]
	var p1 = this.positions[i-1]
	return (p2.distanceFrom(p1) / 1000 / this.getDeltaTime(i, i-1))
}

// returns delta t in hours, i > j
function Track_getDeltaTime(i, j)
{
	return (this.dates[i].getTime() - this.dates[j].getTime()) / (1000 * 60 *60)
}

function Track_getAvSpeed()
{
	if (i == 0)  return 0
	var p2 = this.positions.last()
	var p1 = this.positions[0]
	var dt = (this.dates.last().getTime() - this.dates[0].getTime()) / (1000 * 60 *60)
	return (p2.distanceFrom(p1) / 1000 / dt)
}


function Track_showPointCore()
{
	var i = this.current_point_index;
	var speed = this.getSpeedOfPoint(i)
	var s1 = ('' + speed).substring(0, 5)
	var s2 = ('' + (speed * 0.621118)).substring(0, 5)
	var s = 'Track name: ' + this.getName() + '<br>'
	s += 'Time: ' + this.dates[i].format('hh:nn:ss mm/dd/yyyy ddd')  + '<br>'
	s += 'Speed: ' + s1 + 'km/h, ' + s2 + 'mi/h<br>'
	s += 'Address: ' + this.address
	map.openInfoWindowHtml(this.positions[i], s)	
}

function Track_showPoint(i)
{
	loading_track_busy = true		
	this.address = 'loading...'
	this.current_point_index = i
	this.showPointCore()
	rg = new GReverseGeocoder(map);
	GEvent.addListener(rg, "load", goodresultsp);
	GEvent.addListener(rg, "error", badresultsp);
	rg.reverseGeocode(this.positions[i]);
}

function Track_showPoint2(addr)
{
	this.address = addr
	this.showPointCore()
	loading_track_busy = false	
}
