
var data;
var osMap;
var tracks = [];
var waypoints = [];			
var errmsg = '';

var mineasting = 9999999;
var maxeasting = -1;
var minnorthing = 9999999;
var maxnorthing = -1;


// Gets filename from the parameter string (?f=filename)
// and passes it to the parser to extract the data.
//
function init() 
{  	
	var queryString = window.location.search.substring(1);

	var fileName;
	
	if  (queryString.length > 0)
	{
		if (queryString.indexOf("f=") > -1)
		{
			fileName = queryString.substring(queryString.indexOf("f=") + 2);
		}
	}
	
	if	(fileName && fileName.length > 4)
	{ 	
		var xotree = new XML.ObjTree();
		data = xotree.parseHTTP(fileName,{});
	}
	else
	{
		error('No map data file name supplied.');	
		return;	
	}
	
	// This commented-out code uses the filename  
	// (minus the ".gpx") as the title of the page ...   
	// 
	// var heading = document.getElementById("pageheading");
	// heading.innerHTML = fileName.substring(0, fileName.length - 4); 
	
	// This code uses the filename (minus .gpx) as the page title ...
	document.title = fileName.substring(0, fileName.length - 4); 
	 
	
	// Workaround so that script works with Firefox 3.0 
	//  and Safari 3.1. Can be removed once OpenSpace
	//  is based on v2.6 (or later) of OPenLayers.
	 
	OpenLayers.Renderer.SVG.prototype.supported = function() {
        var svgFeature = "http://www.w3.org/TR/SVG11/feature#";
        return (document.implementation &&
           (document.implementation.hasFeature("org.w3c.svg", "1.0") ||
            document.implementation.hasFeature(svgFeature + "SVG", "1.1") ||
            document.implementation.hasFeature(svgFeature + "BasicStructure", "1.1") ));
	};
	
	if  (data)
	{
		doGPXOverlay(data);
		
		if	(tracks.length == 0 && waypoints.length == 0)
		{
			error('No data found - may not be a valid GPX file');
			return;
		}
		
		displayMap();
		displayData();
	}
	else
	{
		error('Data parse problem. Cannot load map data file.')
	}
}  


//  Runs through all the data (tracks, routes and waypoints) extracted from the
//  GPX file and converts each point into a form suitable for use by OpenSpace.
//
function doGPXOverlay(data)
{
	var t = data.gpx.trk;
	var r = data.gpx.rte
	var wp = data.gpx.wpt;

	if  (typeOf(t) == 'array')
	{
		for (var i = 0; i < t.length; i++) 
		{
			var track = new Object();
			track.name = t[i].name;
			track.points = [];

			var seg = t[i].trkseg;

			if (typeOf(seg) == 'array') 
			{
				for (var j = 0; j < seg.length; j++) 
				{
					for (var k = 0; k < seg[j].trkpt.length; k++)
					{
						track.points.push(makeTrackPoint(seg[j].trkpt[k]));
						
					}
				}
			}

			if (typeOf(seg) == 'object') 
			{
				for (var j = 0; j < seg.trkpt.length; j++) 
				{
					track.points.push(makeTrackPoint(seg.trkpt[j]));
				}
			}
			
			tracks.push(track);
		}
	}

	if  (typeOf(t) == 'object')
	{
		var track = new Object();
		track.name = t.name;
		track.points = [];

		var seg = t.trkseg;

		if (typeOf(seg) == 'array') 
		{
			for (var i = 0; i < seg.length; i++) 
			{
				for (var j = 0; j < seg[i].trkpt.length; j++)
				{
					track.points.push(makeTrackPoint(seg[i].trkpt[j]));
				}
			}
		}

		if (typeOf(seg) == 'object') 
		{
			for (var i = 0; i < seg.trkpt.length; i++) 
			{
				track.points.push(makeTrackPoint(seg.trkpt[i]));
			}
		}
		
		tracks.push(track);
	}


	if  (typeOf(r) == 'object')
	{
		var route = new Object();
		route.name = r.name;
		route.points = [];
	
		var seg = r.rtept;
		
		if (typeOf(seg) == 'array') 
		{
			for (var i = 0; i < seg.length; i++) 
			{
				route.points.push(makeTrackPoint(seg[i]));
			}
		}
		else
		{
			route.points.push(makeTrackPoint(seg));
		}
		
		tracks.push(route);
	}


	if  (typeOf(r) == 'array')
	{
		for (var i = 0; i < r.length; i++) 
		{
			var route = new Object();
			route.name = r[i].name;
			route.points = [];
			
			var seg = r[i].rtept;
	
			if (typeOf(seg) == 'array') 
			{
				for (var j = 0; j < seg.length; j++) 
				{
					route.points.push(makeTrackPoint(seg[j]));
				}
			}
			else
			{
				route.points.push(makeTrackPoint(seg));
			}

			tracks.push(route);
		}
	}

	if  (typeOf(wp) == 'array')
	{
		for (var i = 0; i < wp.length; i++) 
		{
			storeWaypoint(wp[i]);
		}
	}

	if  (typeOf(wp) == 'object')
	{
		storeWaypoint(wp);
	}
}


// Stores a waypoint for subsequent display 
//
function storeWaypoint(lonlat)
{
	if (!lonlat) 
	{
		return;
	}

	var wp = makeWaypoint(lonlat);
	
	if (wp) 
	{
		var waypoint = new Object();
		
		waypoint.mappoint = wp;
		waypoint.name = lonlat['name'];
		waypoint.cmt = lonlat['cmt'];
		waypoint.desc = lonlat['desc'];
		
		waypoints.push(waypoint);
	}
}


// Converts a track or route point from Lon/Lat to OpenSpace format
//
function makeTrackPoint(lonlat)
{
	var pos = new OpenLayers.LonLat(lonlat['-lon'], lonlat['-lat']);
	var gridProjection = new OpenSpace.GridProjection();
	var mp = gridProjection.getMapPointFromLonLat(pos);
	checkBounds(mp);
	return new OpenLayers.Geometry.Point(mp.getEasting(), mp.getNorthing());
}


// Converts a waypoint from Lon/Lat to OpenSpace format
//
function makeWaypoint(lonlat)
{
	var pos = new OpenLayers.LonLat(lonlat['-lon'], lonlat['-lat']);
	var gridProjection = new OpenSpace.GridProjection();
	var mp = gridProjection.getMapPointFromLonLat(pos);
	checkBounds(mp);
	return new OpenSpace.MapPoint(mp.getEasting(), mp.getNorthing());
}


// Determines if a point lies outside the existing known bounds
// of the map, and if so extends those bounds to accommodate it. 
//
function checkBounds(mp)
{
	if	(mp.getEasting() < mineasting) 
	{
		mineasting = mp.getEasting();
	}

	if	(mp.getEasting() > maxeasting) 
	{
		maxeasting = mp.getEasting();
	}

	if	(mp.getNorthing() < minnorthing) 
	{
		minnorthing = mp.getNorthing();
	}

	if	(mp.getNorthing() > maxnorthing) 
	{
		maxnorthing = mp.getNorthing();
	}
}


// Initialises the map at the highest zoom level that will allow  
// all of the tracks, routes and waypoints to be visible. 
//
function displayMap() 
{
	osMap = new OpenSpace.Map('map');  
	var zoomLevel = osMap.getZoomForExtent(new OpenSpace.MapBounds(mineasting, minnorthing, maxeasting, maxnorthing));
	osMap.setCenter(new OpenSpace.MapPoint((mineasting + maxeasting) / 2 , (minnorthing + maxnorthing) / 2), zoomLevel);
}


// Displays a single line for each of the included tracks and/or routes,
// plus a single marker (with default or custom icon) for each waypoint.
//
function displayData() 
{
	if	(tracks.length > 0)
	{
 		vectorLayer = osMap.getVectorLayer();    
	}
	
	for (var i = 0; i < tracks.length; i++)
	{
		var lineString = new OpenLayers.Geometry.LineString(tracks[i].points); 
	
		var style_red = 
		{ 
			strokeColor: "#FF0000", 
			strokeOpacity: 0.7, 
			strokeWidth: 4 
		};
		 
		var lineFeature = new OpenLayers.Feature.Vector(lineString, null, style_red); 
		vectorLayer.addFeatures([lineFeature]); 
	}
	
	for (var i = 0; i < waypoints.length; i++) 
	{
		var html;
		
		if  (waypoints[i].desc && waypoints[i].desc.length > 0)
		{
			html = waypoints[i].desc;
		}
		else if (waypoints[i].cmt && waypoints[i].cmt.length > 0)
		{
			html = waypoints[i].cmt;
		}	
		
		if  (waypoints[i].name.length > 4)
		{
			if (waypoints[i].name.search(/.png$/i) > -1)
			{
				var icon = new OpenSpace.Icon(waypoints[i].name, new OpenLayers.Size(34, 45), new OpenLayers.Pixel(-17, -45));
				osMap.createMarker(waypoints[i].mappoint, icon, html);			
			}
			else
			{
				osMap.createMarker(waypoints[i].mappoint, null, html); 
			}		
		}
		
	}
}


function error(msg)
{
	errmsg += '<li>' + msg + '</li>\n';
	var errDiv = document.getElementById('error');
	errDiv.innerHTML = '<h4>Error!</h4><ul>' + errmsg + '</ul>' ;
	errDiv.style.display = 'block';
}


function typeOf(value) 
{    
	var s = typeof value;    
	
	if (s === 'object') 
	{        
		if (value) 
		{            
			if (value instanceof Array) 
			{                
				s = 'array';            
			}        
		} 
		else 
		{            
			s = 'null';        
		}    
	}    
	return s;
}

