var xml_doc

function zoomLevel (spanLon, spanLat) {
  var compareTo = Math.max(spanLon, spanLat * 1.33);
  if (compareTo < 0.00690937042236328) return 0;
  if (compareTo < 0.013818740844726562) return 1;
  if (compareTo < 0.027637481689453125) return 2;
  if (compareTo < 0.05527496337890625) return 3;
  if (compareTo < 0.1105499267578125) return 4;
  if (compareTo < 0.221099853515625) return 5;
  if (compareTo < 0.44219970703125) return 6;
  if (compareTo < 0.8843994140625) return 7;
  if (compareTo < 1.768798828125) return 8;
  if (compareTo < 3.53759765625) return 9;
  if (compareTo < 7.0751953125) return 10;
  if (compareTo < 14.150390625) return 11;
  if (compareTo < 28.30078125) return 12;
  if (compareTo < 56.6015625) return 13;
  if (compareTo < 113.203125) return 14;
  if (compareTo < 226.40625) return 15;
  if (compareTo < 452.8125) return 16;
  if (compareTo < 905.625) return 17;
  return 17;
}

function calcLatLonDist (Lat1, Lon1, Lat2, Lon2, UnitFlag) {
	var cPI = Math.PI;
	var LatRad1 = Lat1 * cPI / 180;
	var LonRad1 = Lon1 * cPI / 180;
	var LatRad2 = Lat2 * cPI / 180;
	var LonRad2 = Lon2 * cPI / 180;
	var LonRadDif = Math.abs(LonRad1 - LonRad2);
	var X = Math.sin(LatRad1) * Math.sin(LatRad2) + Math.cos(LatRad1) * Math.cos(LatRad2) * Math.cos(LonRadDif);
	var RadDist = Math.atan(-X / Math.sqrt(-X * X + 1)) + 2 * Math.atan(1);
	var DistMI = RadDist * 3958.754;
	var DistKM = DistMI * 1.609344;
	return  (UnitFlag == "K") ? DistKM : DistMI;
}

var map, baseIcon, points;

function setIcon() {
	baseIcon = new GIcon();
	baseIcon.shadow = "images/shadow50.png";
	baseIcon.iconSize = new GSize(20, 34);
	baseIcon.shadowSize = new GSize(37, 34);
	baseIcon.iconAnchor = new GPoint(9, 34);
	baseIcon.infoWindowAnchor = new GPoint(9, 2);
	baseIcon.infoShadowAnchor = new GPoint(18, 25);
}

function symImageFile(sym) {
  switch (sym){
    case 'Campground':
      return "gpx_campground.png";
    case 'Convenience Store':
      return "gpx-convenience-store.png";
    case 'Gas Station':
      return "gpx-gas-station.png";
    case 'Hotel':
      return "gpx-lodging.png";
    case 'Museum':
      return "gpx-museum.png";
    case 'Restaurant':
      return "gpx-restaurant.png";
    case 'Restroom':
      return "gpx-restroom.png";
    case 'Waypoint':
      return "mm_20_red.png";
   }
  return "mm_20_red.png";
}

function pointInsideViewPort(lat, lon) {
	var bounds = map.getBoundsLatLng();
	if (bounds.minY <= lat && lat <= bounds.maxY &&
	    bounds.minX <= lon && lon <= bounds.maxX) {
	  return true;
	}
	return false;
}

function elementValue(parentNode, elementName) {
	var nodeList = parentNode.getElementsByTagName(elementName);
	if (nodeList.length > 0) {
		return nodeList[0].childNodes[0].nodeValue; 
	}
	return null;
}


function createMarker(point, sym, html) {
  var icon = new GIcon(baseIcon);
  icon.image = "images/" + symImageFile(sym);
  var marker = new GMarker(point, icon);
  GEvent.addListener(marker, "click", function() {
    marker.openInfoWindowHtml(html);
  });
  return marker;
}

function createMarkers() {
  setIcon();
  itemNodeList = xml_doc.getElementsByTagName("wpt");
  for (i = 0; i < itemNodeList.length; i++) {
    var lat = itemNodeList[i].getAttribute("lat");
    var lon = itemNodeList[i].getAttribute("lon");
    if (pointInsideViewPort(lat, lon)) {
		var name = elementValue(itemNodeList[i], "name");
		var cmt = elementValue(itemNodeList[i], "cmt");
		var sym = elementValue(itemNodeList[i], "sym");
		var type = elementValue(itemNodeList[i], "type");
  		var html = "Name    :" + name + "<br/>"
  		         + "Comment :" + cmt + "<br/>"
  		         + "Type    :" + type + "<br/>"
  		         + "Lat     :" + lat + "<br/>"
  		         + "Lon     :" + lon + "<br/>";
  	  var point = new GPoint(lon, lat);
	  var marker = createMarker(point, sym, html);
  	  map.addOverlay(marker);
    }
  }
}


function readFile() {
  //alert("inside readFile()");
  var maxLat=-90, minLat=90, maxLon=-180, minLon=180, prevLat, prevLon, totalDist = 0, i, j, iHTML
  map.clearOverlays();
  var points = [];

  var collNodeList;
  var itemTag;
  if (xmlCollType) {
	collNodeList = xml_doc.getElementsByTagName(xmlCollType);
	itemTag = xmlCollType + "pt";
  } else {
	var collNodeList = xml_doc.getElementsByTagName("trk");
	if ((collNodeList && collNodeList.length)) {
		xmlCollType = "trk";
		itemTag = "trkpt";
	} else {
		collNodeList = xml_doc.getElementsByTagName("rte");
		if ((collNodeList && collNodeList.length)) {
		  xmlCollType = "rte";
		  itemTag = "rtept";
		} 
	}
  }
  //alert(itemTag + "\ncollNodeList.length:" + collNodeList.length)
  iHTML = 	"<table style=display:block>";
  var collItemName, isMapped = false;
  for (j = 0; j < collNodeList.length; j++) {
      itemNodeList = collNodeList[j].getElementsByTagName("name");
      if (itemNodeList.length > 0) {
        collItemName = itemNodeList[0].childNodes[0].nodeValue; 
      }
      //alert(itemNodeList.length + "\n" + collItemName)
	  itemNodeList = collNodeList[j].getElementsByTagName(itemTag);
	if ((j == 0 && collNodeList.length == 1) || j == xmlCollItem || xmlCollItemName == 'All') {
      for (i = 0; i < itemNodeList.length; i++) {
	    var lat = itemNodeList[i].getAttribute("lat");
	    var lon = itemNodeList[i].getAttribute("lon");
	    minLat = Math.min(lat,minLat);
	    maxLat = Math.max(lat,maxLat);
	    minLon = Math.min(lon,minLon);
	    maxLon = Math.max(lon,maxLon);
		if (i != 0) {
		  totalDist += calcLatLonDist (prevLat, prevLon, lat, lon, "M") 
		}
		points.push(new GPoint(lon,lat));
	    prevLat = lat;
	    prevLon = lon;
	  }
	  var latSpan = Math.abs(maxLat - minLat);
	  var lonSpan = Math.abs(maxLon - minLon);
	  var zoomLev = zoomLevel(lonSpan, latSpan);

	  map.centerAndZoom(new GPoint(minLon + lonSpan/2, minLat + latSpan/2),zoomLev);
	  map.addOverlay(new GPolyline(points));
	  isMapped = true;
	}
	if (collNodeList.length > 1) {
	  if (j == 0) {
	    iHTML += 	"<tr><td><div id=" + xmlFileName + " class=gpx onClick=showMap(this.id,'" + xmlCollType + "',null,'All')>All</div></td></tr>";
	  }
	  iHTML += 	"<tr><td><div id=" + xmlFileName + "___" + j + " class=gpx onClick=showMap(this.id.substring(0,this.id.lastIndexOf('___')),'" + xmlCollType + "'," + j + ",'" + collItemName + "')>" + collItemName + "</div></td></tr>";
	}
  }
  if (!isMapped) {
    idDist.innerHTML = "<span class=alert>Select one of the include routes/tracks or All</span>";
    if (collNodeList.length > 0) {
      itemNodeList = collNodeList[0].getElementsByTagName(itemTag);
      if (itemNodeList.length > 0) {
		map = new GMap(document.getElementById("map"));
		map.addControl(new GLargeMapControl());
		map.addControl(new GMapTypeControl());
		map.centerAndZoom(new GPoint(itemNodeList[0].getAttribute("lon"), itemNodeList[0].getAttribute("lat")),6);
      }
    }
  } else {
    idDist.innerHTML = Math.round(totalDist*100)/100 + " miles";
  }
  iHTML += "</table>";
  if (typeof(xmlCollItem)=='undefined' && collNodeList.length > 1) {
	document.getElementById(xmlFileName).className="gpxGrp";
	document.getElementById(xmlFileName).insertAdjacentHTML("afterEnd",iHTML);
	document.getElementById(xmlFileName).outerHTML = "<span id=" + xmlFileName + " class=gpxGrp onclick=toggleListDisplay(this)>" + document.getElementById(xmlFileName).innerHTML + "</span>";
  }
  if (xmlCollItemName != 'All') {
    createMarkers();
  }
}  


function importXML() {
	var request = GXmlHttp.create();
	request.open("GET", "gpx/" + xmlFileName, true);
	request.onreadystatechange = function() {
	  if (request.readyState == 4) {
	    xml_doc = request.responseXML;
	    var markers = xml_doc.documentElement.getElementsByTagName("trkpt");
	    readFile()
	  }
	}
	request.send(null);
 }

function initMap() {
	map = new GMap(document.getElementById("map"));
	map.addControl(new GLargeMapControl());
	map.addControl(new GMapTypeControl());
    map.centerAndZoom(new GPoint(-93.096359, 41.840759), 13);
}

var xmlFileName
var xmlCollType
var xmlCollItem
var xmlCollItemName

function showMap(fileName, type, item, name) {
	xmlCollItemName = name;
  	var nm = "";
  	if (typeof (name) != "undefined") {
  	  nm = " - " + name;
  	}
    xmlCollType = type;
	xmlCollItem = item;
//	alert("type:" + type + "\nitem:" + item + "\ntypeof: " + (typeof(item)=='undefined') + "\nxmlFileName: " + xmlFileName + "\nfileName: " + fileName)
  if (xmlFileName != fileName) {
	idDist.innerHTML = "<span class=alert>Loading...</span>";
  	xmlFileName = fileName;
	idFile.innerHTML = xmlFileName.replace(/\\/g , " - ") + nm;
	setTimeout("importXML()",1000);
  } else if (xmlCollItem >= 0) {
    idDist.innerHTML = "<span class=alert>Calculating...</span>";
	idFile.innerHTML = xmlFileName.replace(/\\/g , " - ") + nm;
	setTimeout("importXML()",100);
  }
}

function toggleListDisplay(elem) {
  //alert(elem.parentNode.childNodes[1])
  tblElem = getElementByClassName('fileList', elem.parentNode)
  if (tblElem) {
    tblElem.style.display = (tblElem.style.display=="none") ? "block" : "none";
  }
}

function showIt() {
    xml_doc = (new DOMParser()).parseFromString(idpasteGPX.value, "text/xml");
    var markers = xml_doc.documentElement.getElementsByTagName("trkpt");
    readFile()
}

function hasClassName(element, className) {
  if (!element) return;
  var hasClass = false;
  var classNms = element.className.split(' ');
  for (var i=0; i<classNms.length;i++) {
    if (classNms[i] == className) {
      hasClass = true;
    }
  }
  return hasClass;
}

function getElementsByClassName(className, parentElement) {
  var children = (parentElement || document.body).getElementsByTagName('*');
    var elements = [];
    for (var i=0; i<children.length; i++) {
        if (hasClassName(children[i], className)) {
      elements.push(children[i]);
    }
    }; 
    return elements;
}
function getElementByClassName(className, parentElement) {
  var elements = getElementsByClassName(className, parentElement);
  if (elements) {
    return elements[0];
  }
  return null;
}

