/**
 	 
 		Copyright 2008 NDW Ltd. http://ndrw.co.uk/
 	 
		This program is free software: you can redistribute it and/or modify
		it under the terms of the GNU General Public License as published by
		the Free Software Foundation.
		
		This program is distributed in the hope that it will be useful,
		but WITHOUT ANY WARRANTY; without even the implied warranty of
		MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
		GNU General Public License for more details.
		
		To see a copy of the GNU General Public License go to <http://www.gnu.org/licenses/>.
		
		Version 1.00
 
 */  
 
// JavaScript funtions/methods to display an OSGB map on a web page
 
 

	// Global variables, this is all you need to change, honest :-)
var gbCheckTime	= false;		// set to true to enable time checking
var gbDebug			= false;		// se to true to turn on debuging
var gTimeInc		= 20000; 	// Milliseconds between waypoints i.e. 20 seconds = 20000

	// Advanced feature, ignore this it just disables all Ordnance Survey calls so the prog can run 
	// on your own PC for testing, i.e. set to false
var gbUseOsFuncs	= true;

/* 
 * This function loads the XML document from the specified URL, and when
 * it is fully loaded, passes that document and the url to the specified
 * handler function.  This function works with any XML document
 * 
 * url		Path to file, on current server
 * handler	Function to call once the XML file is loaded
 *  
 */  
function loadXML(url, handler) 
	{
	debug('loadXML url ' + url);
	try
	{
				// Use the standard DOM Level 2 technique, if it is supported
		if (document.implementation && document.implementation.createDocument) 
			{
				// Create a new Document object
			var xmldoc = document.implementation.createDocument("", "", null);
				// Specify what should happen when it finishes loading
			xmldoc.onload = function() 
				{ 
				handler(xmldoc, url); 
				}
			xmldoc.async = true;
				
				// And tell it what URL to load
			xmldoc.load(url);
			}
		    
			// Otherwise use Microsoft's proprietary API for Internet Explorer
	    else if (window.ActiveXObject) 
			{ 
				var xmldoc = new ActiveXObject("Microsoft.XMLDOM");   // Create doc.
				xmldoc.onreadystatechange = function() 
				{              
					// Specify onload
				if (xmldoc.readyState == 4) 
					handler(xmldoc, url);
				}
			xmldoc.load(url);                                     // Start loading!
			}
		else
			{
			alert("Failed loading the GPX file " + url);
			return;
			}
	}

  catch(e)
    {
    alert('Failure loading the GPX file ' + url + '\n' + e.message);
    return;
    }
	}
/**
 *
 * The handler function called via loadXML
 * 
 * xmlDoc	Open handle to the XML doc
 * url		Path to file on this server (not used)
 *    
 */   
function parseGPX(xmlDoc, url)
{
try
	{
	debug('parseGPX xmlDoc ' + url);

	var gridProjection;
	var osMap;

//	if(!xmlDoc.documentElement.getElementsByTagName('gpx'))
	if(!xmlDoc.documentElement)
		alert(url + ' Does not seem to be a valid file, we will try and use this file just in case it is');
		
	if(gbUseOsFuncs)
		{
		osMap = new OpenSpace.Map('map');
		gridProjection = new OpenSpace.GridProjection();
		}

	centerMap(osMap, xmlDoc);
		// Add the track
	addTrack(osMap, xmlDoc);		
	}
  catch(e)
    {
    alert(e.message);
    return;
    }

}
/**
 *
 * Add a track by pasing the XML file  between <WayPoint> tags
 * 
 * osMap		Open handle to the OS Map
 * xmlDoc	Open handle to the XML file
 *    
 */  
function addTrack(osMap, xmlDoc)
	{
	var array;
	var arrayWpts = getWpts(xmlDoc);

	var bDisplay	= false;
		
	var gpxDate;

	var newDate;
				
	var points 		= new Array();
	var pos;

 		// Define the line style
	var style_red =
		{
	   strokeColor: "#FF00FF",
	   strokeOpacity: 0.7,
	   strokeWidth: 4,
	   pointRadius: 6,
	   pointerEvents: "visiblePainted"
		}

	var timeNew;
	var timeOld 	= 0;
			
	if(gbUseOsFuncs)
		{
		var vectorLayer = osMap.getVectorLayer();
		osMap.addLayer(vectorLayer);
		}
		
	debug("loop " + arrayWpts.length); 
	for(var lLoop = 0; lLoop < arrayWpts.length;  lLoop++)
		{
		bDisplay = false;
		if(arrayWpts[lLoop]['time'])
			{			
			gpxDate = arrayWpts[lLoop]['time'];
			gpxDate = gpxDate.replace(/[A-Z]/ig, ' ');

			array = gpxDate.split(/[- :]/);
			
				// Needed because of Firefox it would not parse '2008-02-12 09:47:09'
			newDate = new Date(array[0], array[1] - 1, array[2], array[3], array[4], array[5]);

			timeNew = new Date(newDate);
			if(timeNew.getTime() > (timeOld + gTimeInc))
				{
				timeOld = timeNew.getTime();
				bDisplay = true;
				}			 
			}
		else
			bDisplay = true;
		
		if(bDisplay || gbCheckTime == false)
			{	
			if(gbUseOsFuncs)
				{
				pos = getOSGB(parseFloat(arrayWpts[lLoop]['lon']), parseFloat(arrayWpts[lLoop]['lat']));
				var point = new OpenLayers.Geometry.Point(Math.round(pos.getEasting()), Math.round(pos.getNorthing()));
				points.push(point);
				}
			debug('addTrack latVal ' + arrayWpts[lLoop]['lat'] + ' lonVal ' + arrayWpts[lLoop]['lon'] + ' date ' + gpxDate );
			}
		}
		// create a line feature from a list of points
	if(gbUseOsFuncs)
		{
		var lineString 	= new OpenLayers.Geometry.LineString(points);
		var lineFeature 	= new OpenLayers.Feature.Vector(lineString, null, style_red);
		
		vectorLayer.addFeatures([lineFeature]);
		}
	}
			
/**
 *
 * Centers the map using the <bounds minlat="53.33001852035523" minlon="-1.73298597335815" maxlat="53.36278438568115" maxlon="-1.64440870285034"/>
 * 
 * osMap		Open handle to the OS Map
 * xmlDoc	Open handle to the XML file
 *    
 */  
function centerMap(osMap, xmlDoc)
	{
	try
	{
	var Bounds = xmlDoc.documentElement.getElementsByTagName('bounds');
	if(Bounds.length > 0)
		{
			// Centers the map using <bounds minlat="53.33001852035523" minlon="-1.73298597335815" maxlat="53.36278438568115" maxlon="-1.64440870285034"/>
		var minlat  = Bounds[0].getAttribute('minlat');
		var minlon  = Bounds[0].getAttribute('minlon');
		var maxlat  = Bounds[0].getAttribute('maxlat');
		var maxlon  = Bounds[0].getAttribute('maxlon');

		var llLH = getOSGB(minlon, maxlat);
		var llRH = getOSGB(maxlon, minlat);							
	
			// left, top, right, bottom				
		if(gbUseOsFuncs)
			{
			var bounds = new OpenLayers.Bounds(llLH.lon, llLH.lat, llRH.lon, llRH.lat);
			osMap.zoomToExtent(bounds);
			}
			 
		debug('centerMap minlat ' + minlat + ' minlon ' + minlon + ' maxlat ' + maxlat + ' maxlon ' + maxlon);
		}
	else
		alert("centerMap failure, no \'bounds\' element in the gpx file");
	}
  catch(e)
    {
		alert("centerMap failure caught, no \'bounds\' element in the gpx file");
    }
    return;
	}


/**
 *
 * return the OSGB values for the lat long
 * 
 */    
function getOSGB(lon, lat)
	{
	var pos;
	if(gbUseOsFuncs)
		{
		var gridProjection = new OpenSpace.GridProjection();
	
		var lonlat = new OpenLayers.LonLat(lon, lat);
		pos = gridProjection.getMapPointFromLonLat(lonlat);
		}
	
	return(pos);
	}

/**
 *
 * Gets an associated array of waypoints from a GPX file
 * 
 */   
function getWpts(xmlDoc)
	{
	var kount 		= 0;
	var time_ele;
	var Wpts 		= new Array();

		// Look for GPX element  <trk> 
	var Trk = xmlDoc.documentElement.getElementsByTagName("trk");
	
	for (var i = 0; i < Trk.length; i++)
		{
		// Look for GPX element  <trkseg> 
		TrkSeg = Trk[i].getElementsByTagName('trkseg');
		for(var j = 0; j < TrkSeg.length; j++)
			{
				// Look for GPX element  <trkpt lat="53.330619335" lon="-1.661531925"> 
			TrkPnts = TrkSeg[j].getElementsByTagName('trkpt');
			for(var k = 0; k < TrkPnts.length; k++)
				{
				Wpts[kount] = new Array();
					
					// from the GPX <trkpt> element get the <time>2008-02-12T09:47:09Z</time>
				time_ele	= TrkPnts[k].getElementsByTagName('time');
				
				Wpts[kount]['lat']	= TrkPnts[k].getAttribute('lat');
				Wpts[kount]['lon'] 	= TrkPnts[k].getAttribute('lon');
				Wpts[kount]['time']	= time_ele[0].childNodes[0].nodeValue;
								
				kount++;
				}
			}
		} 
	return(Wpts);		
	}
/**
 *
 * Simple debug class, writes date to the <p id="debug"></p> in the html page
 * 
 */   	
function debug(data)
	{
	if(!gbDebug)
		return;
		
	var elementDebug	 	= document.getElementById("debug");
	var oldDisplay 		= elementDebug.innerHTML;

	elementDebug.innerHTML = oldDisplay + data + "<br />";
	}

