/**
  * (c) Paul Uithol, SMARTposition
  * http://www.smartposition.nl
  * 
  * date: 06 jun 2007
  * version: 0.21
  * -----------------
  * 0.1		supports wpt
  * 0.2		supports routes, tracks and track segments
  * 0.21		[SPE] Optimized the javascript
  *
  *
  * BUGS
  * -
  */
  
GPX.wpt = 1;
GPX.trk = 2;
GPX.rte = 3;

function GPX() {
	var that = this;
}

GPX.prototype = {
	waypoints: {}
};

GPX.prototype.getAll = function() {
	if (this.waypoints) {
		return this.waypoints;
	}
	
	return (res = {});
}

GPX.prototype.getWaypoints = function() {
	var res = this.waypoints["wpt"] || new Array();
	return res;
}

GPX.prototype.getRoutes = function() {
	var res = this.waypoints["rte"] || new Array();
	return res;
}

GPX.prototype.getTracks = function() {
	var res = this.waypoints["trk"] || new Array();
	return res;
}

GPX.prototype.load = function(xml) {
	this.xml = xml;
	
	this.waypoints["wpt"] = new Array();
	this.waypoints["rte"] = new Array();
	this.waypoints["trk"] = new Array();
	
	// select loose waypoints
	var wpt = xml.documentElement.getElementsByTagName("wpt");
	if (wpt && wpt.length){
		 this.waypoints["wpt"] = this.parseWaypoints(wpt, GPX.wpt);
	}//end if-wpt
	
	// select routes
	var rte = xml.documentElement.getElementsByTagName("rte");
	if (rte && rte.length) {
		for (var i = 0; i < rte.length; i++) {	// loop through routes
			var rtept = rte[i].getElementsByTagName("rtept");
			
			if (rtept && rtept.length) {
				// add waypoints to route
				this.waypoints["rte"][i] = this.parseWaypoints(rtept, GPX.rte);
				
				// add additional information about the route itself, like name and desc
				this.addChildElementsAsData(rte[i], this.waypoints["rte"][i], "rtept");
			}
		}
	}//end if- rte
	
	// select tracks
	var trk = xml.documentElement.getElementsByTagName("trk");
	if (trk && trk.length) {
		for (var i = 0; i < trk.length; i++) {	// loop through tracks
			// add additional information about the track itself, like name and desc
			this.waypoints["trk"][i] = new Array();
			this.addChildElementsAsData(trk[i], this.waypoints["trk"][i], "trkseg");
			
			var trkseg = trk[i].getElementsByTagName("trkseg");
		
			// loop through track segments
			for (var j = 0; j < trkseg.length; j++) {
				var trkpt = trkseg[j].getElementsByTagName("trkpt");
				
				if (trkpt && trkpt.length) {
					// add waypoints to the trackseg
					this.waypoints["trk"][i][j] = this.parseWaypoints(trkpt, GPX.trk);
					
					// add additional information about the trackseg itself, like name and desc
					this.addChildElementsAsData(trkseg[j], this.waypoints["trk"][i][j], "trkpt");
				}
			}
		}
	}//end if-trk
	
	//Log.write("Parsed " + this.waypoints["wpt"].length + " waypoint(s), " + this.waypoints["rte"].length + " route(s), " + this.waypoints["trk"].length + " track(s)");
	
	//console.group("Waypoints:");
	//console.log(this.waypoints);
	//console.groupEnd();
	
	return this.waypoints;
}

GPX.prototype.addChildElementsAsData = function(fromNode, toNode, untilElement) {
	if (fromNode.childNodes.length) {
		for(var i = 0; (fromNode.childNodes[i].nodeName != untilElement) && i < fromNode.childNodes.length; i++) {
			if (fromNode.childNodes[i].firstChild) {
				childNode = fromNode.childNodes[i];
				childName = childNode.nodeName;
				toNode[childName] = childNode.firstChild.nodeValue;
				
				//add extensions
				if(childName == "extensions"){
					for(var j=0;j<childNode.childNodes.length;j++){
						var extensionNodeName = childNode.childNodes[j].nodeName;
						
						if(extensionNodeName == "spx" || extensionNodeName == "s:spx"){
							var extensionNode = childNode.childNodes[j];
							//alert(extensionNode.childNodes.length);
							for(var k=0;k<extensionNode.childNodes.length;k++){
								
								if(extensionNode.childNodes[k].getAttribute("v")){
									extensionName = extensionNode.childNodes[k].nodeName;
									//strip of namespace
									extensionName = extensionName.substring(extensionName.indexOf(":") + 1);
									toNode[extensionName] = extensionNode.childNodes[k].getAttribute("v");
								}//end if
							}//end for spx
							//return;
						}//end if spx
					}//end for
				}//end if extensions
			}
		}
	}
}

GPX.prototype.parseWaypoints = function(wpt, type) {
	var tmp = "";
	//Log.write("Parsing " + wpt.length + " wpt's of type " + type);
	
	var results = new Array();
	
	for (var i = 0; i < wpt.length; i++) {
		
		// set default values for variables
		var waypoint = {};
		
		// get values for waypoint child elements
		waypoint = new GLatLng(parseFloat(wpt[i].getAttribute("lat")),
							parseFloat(wpt[i].getAttribute("lon")));
		
		//[0.21 @ 06/06/07] insert null instead of empty string
		//if ((tmp = this.getChildElementValues(wpt[i], "ele", "")[0]) != ""){ waypoint.ele = tmp;}
		if ((tmp = this.getChildElementValues(wpt[i], "time", "")[0]) != ""){ waypoint.time = tmp;}
		if ((tmp = this.getChildElementValues(wpt[i], "magvar", "")[0]) != ""){waypoint.magvar = tmp;}
		if ((tmp = this.getChildElementValues(wpt[i], "name", "")[0]) != ""){ waypoint.name = tmp;}
		
		if ((tmp = this.getChildElementValues(wpt[i], "cmt", "")[0]) != ""){ waypoint.cmt = tmp;}
	  	if ((tmp = this.getChildElementValues(wpt[i], "desc", "")[0]) != ""){ waypoint.desc = tmp;}
	  	//if ((tmp = this.getChildAttributeValue(wpt[i], "link", "href", "")) != ""){waypoint.link = tmp;}
	  	if ((tmp = this.getChildElementValues(wpt[i], "sym", "")[0]) != ""){ waypoint.sym = tmp;}
	  	//if ((tmp = this.getChildElementValues(wpt[i], "type", "")[0]) != ""){ waypoint.type = tmp;}
	  	
	  	//[0.21 @ 06/06/2007] added extension tags
	  	if(wpt[i].getElementsByTagName("extensions").length) {
		  	var nameSpace = "";
			if (navigator.appName == "Microsoft Internet Explorer"){
					var nameSpace = "s:";
	  		}//end if bowser check
	  		
	  		var extensions_spx = wpt[i].getElementsByTagName("extensions")[0].getElementsByTagName(nameSpace+"spx")[0];
	  		if ((tmp = this.getChildAttributeValue(extensions_spx, nameSpace+"color", "v", "")) != ""){waypoint.colour = tmp;}
	  		if ((tmp = this.getChildAttributeValue(extensions_spx, nameSpace+"spd", "v", "")) != ""){waypoint.speed = tmp;}
	  		if ((tmp = this.getChildAttributeValue(extensions_spx, nameSpace+"dst", "v", "")) != ""){waypoint.distance = tmp;}
  		}//end if check extensions
	  	
	  	results[i] = waypoint;
	  	
	}//end for-loop
	
	return results;
}

GPX.prototype.getChildElementValues = function(element, tagName, defaultValue) {
	//console.log(element);
	children = element.getElementsByTagName(tagName);
	results = new Array();
	
	if(children.length && children[0].firstChild != null) {
		for (var i = 0; i < children.length; i++) {
			results[i] = children[i].firstChild.nodeValue;
		}
		return results;
	}
	
	results[0] = defaultValue;
	
	return results;
}

GPX.prototype.getChildAttributeValue = function(element, tagName, attrName, defaultValue) {
	if (element != undefined) {
		children = element.getElementsByTagName(tagName);
	
		if(children.length) {
			return children[0].getAttribute(attrName);
		}
	}
	
	return defaultValue;
}
