/*--------------------------------------------------------------------------*/
/*  Western North Carolina GPS Mapper                                       *
 *  A Google Maps Mashup for WEB 289 - Spring 2008                          *
 *  (c) 2008 Jordan Mitchell                                                *
 *  All rights reserved.                                                    *
/*--------------------------------------------------------------------------*/

// Settinate these up before...
var map;
var allMarkers = [];
var sidebarHTML = "<h2>Route Layers</h2>";

function gmapCommon() {
  if(GBrowserIsCompatible()){
  // Create a topo map layer based on the free Terraserver WMS (Web Mapping Service)
    function WMSCreateMap(name, copyright, baseUrl, layer, minResolution, maxResolution, urlArg )
    {
      var tileLayer = new GTileLayer( new GCopyrightCollection( copyright ), minResolution, maxResolution );
      tileLayer.baseUrl = baseUrl;
      tileLayer.layer = layer;
      tileLayer.getTileUrl = WMSGetTileUrl;
      tileLayer.getCopyright = function () { return copyright; };
      var tileLayers = [ tileLayer ];
      return new GMapType( tileLayers, G_SATELLITE_MAP.getProjection(), name, { errorMessage:"Data Not Available" } );
    }
    // Function to retrieve the tile from the Terraserver WMS
    function WMSGetTileUrl( tile, zoom )
    {
      var southWestPixel = new GPoint( tile.x * 256, ( tile.y + 1 ) * 256);
      var northEastPixel = new GPoint( ( tile.x + 1 ) * 256, tile.y * 256);
      var southWestCoords = G_NORMAL_MAP.getProjection().fromPixelToLatLng( southWestPixel, zoom );
      var northEastCoords = G_NORMAL_MAP.getProjection().fromPixelToLatLng( northEastPixel, zoom );
      var bbox = southWestCoords.lng() + ',' + southWestCoords.lat() +
            ',' + northEastCoords.lng() + ',' + northEastCoords.lat();
      return this.baseUrl + '?VERSION=1.1.1&REQUEST=GetMap&LAYERS=' +
            this.layer + '&STYLES=&SRS=EPSG:4326&BBOX=' + bbox +
                  '&WIDTH=256&HEIGHT=256&FORMAT=image/jpeg&BGCOLOR=0xCCCCCC&EXCEPTIONS=INIMAGE';
    }
    // Create the layer
    var WMS_TOPO_MAP = WMSCreateMap( 'Topo', 'Imagery by USGS / Web Service by TerraServer',
      'http://www.terraserver-usa.com/ogcmap6.ashx', 'DRG', 4, 17, 't' );
    var map = new GMap2(document.getElementById("map"));
    map.addMapType(WMS_TOPO_MAP); // Add the topo map
    map.addMapType(G_PHYSICAL_MAP); // Add the physical map
    map.addControl(new GLargeMapControl3D());
    map.addControl(new GMapTypeControl());
    
    // Add Ads
    var publisher_id = "pub-5006048085075876";
    var adPos = new GControlPosition(G_ANCHOR_BOTTOM_RIGHT, new GSize(7, 30));
    // Set the anchor position and GSize offset to your desired values.
    
    adsManagerOptions = {
      maxAdsOnMap : 2,
      style: 'adunit',
      channel: '3877723853',
      position: adPos
    };
    
    adsManager = new GAdsManager(map, publisher_id, adsManagerOptions);
    adsManager.enable();
    
    map.enableScrollWheelZoom();
  } // End if browser is compatible
  return map;
} // End gmapCommon function

function gmapInitialize() {
  if (GBrowserIsCompatible()) {
    // Initialize the basic Google map
    map = gmapCommon();
    map.setCenter(new GLatLng(35.8005, -82.4770), 8, G_PHYSICAL_MAP);
    loadParseGPX('waterfalls'); // Automatically load & parse the initial view
  } // End if browser is compatible
} // End gmapInitialize function

// *******************************************************
// The following functions are for loading and parsing GPX 
// *******************************************************

// Choose a Line Style
function chooseLineStyle(name, comment) {
	if (comment == "BB" ) {
		return(new Array("#00f0f0",5,.5))
		}
	return(new Array("#ff2000",6,.7))	// Color,Width,Opacity
}

// Create a marker with InfoWindow
function createMarker(map, point, tabarray, icon, pointid) {
  var marker = new GMarker(point, icon);
  GEvent.addListener(marker, "click", function() {
    marker.openInfoWindowTabsHtml(tabarray);
  });
  map.addOverlay(marker);
  allMarkers[pointid] = marker;
  return marker;
}

// Create a function to "click" a marker when you click something else
// (i.e. - a listing in the search results)

function myclick(pointid) {
  GEvent.trigger(allMarkers[pointid], "click");
} 

function navigateMap(lat,lng,zoom){
  map.setCenter(new GLatLng(lat,lng),zoom);
}

function toggleMarkers(){
  for(var mc = 0; mc < allMarkers.length; mc++)
  {
    currentMarker = allMarkers[mc];
    if (currentMarker.isHidden()) {
      currentMarker.show();
    } else {
      currentMarker.hide();
    }
  }
}

// Toggle a route
function toggleRoute(rteOverlay) {
  if(rteOverlay.supportsHide()){
    if(rteOverlay.isHidden()) {rteOverlay.show();} else {rteOverlay.hide();}
  } else {
    // Figure out how to determine if the polyline is added tothe map and
    // toggle it based on that
  }
}

// Toggle an individual track segment
function toggleSegment(segmentOverlay) {
  if(segmentOverlay.supportsHide())
  {
    if(segmentOverlay.isHidden()) {segmentOverlay.show();} else {segmentOverlay.hide();}
  }
  else
  {
    // Figure out a way to determine if the polyline is added to the map and
    // toggle it based on that
  }
}

// *******************************************************
// Load and parse the GPX file
// Adapted from the GPX Loader for Google Maps
// http://www.obviously.com/gis/gpx_loader.html
// *******************************************************

// Information about the GPX file format:
// http://www.topografix.com/gpx_manual.asp
function loadParseGPX(GPXFile){
  
  // Clear the sidebar
  markers = [];
  segmentHTML = '';
  trackSegmentHTML = '';
  trackHTML = '';
  
  sidebarHTML = '<div style="color:red; width: 200px">Loading...<div>';
  // document.getElementById("routeLayers").innerHTML = sidebarHTML;
  
  // Give a loading indicator
  $('tbstatus').update('<p style="text-align:center;"><img src="/images/gphx/ajax-loader.gif"><br>Loading Map...</p>');
  
  sidebarHTML = '<h3>Layers</h3>';
  
  // Modify this to set the icon types used
  var red_pin = new GIcon();
  red_pin.image  		   = "images/markers/mm_20_red.png";
  red_pin.shadow 	     = "images/markers/mm_20_shadow.png";
  red_pin.iconSize  	 = new GSize(12, 20);
  red_pin.shadowSize 	 = new GSize(22, 20);
  red_pin.iconAnchor 	 = new GPoint(6, 20);
  red_pin.infoWindowAnchor = new GPoint(5, 1);
  
  var green_pin = new GIcon();
  green_pin.image  	   = "images/markers/mm_20_green.png";
  green_pin.shadow 	   = "images/markers/mm_20_shadow.png";
  green_pin.iconSize 	 = new GSize(12, 20);
  green_pin.shadowSize = new GSize(22, 20);
  green_pin.iconAnchor = new GPoint(6, 20);
  green_pin.infoWindowAnchor = new GPoint(5, 1);
  
  var blue_pin = new GIcon();
  blue_pin.image  	   = "images/markers/mm_20_blue.png";
  blue_pin.shadow 	   = "images/markers/mm_20_shadow.png";
  blue_pin.iconSize 	 = new GSize(12, 20);
  blue_pin.shadowSize = new GSize(22, 20);
  blue_pin.iconAnchor = new GPoint(6, 20);
  blue_pin.infoWindowAnchor = new GPoint(5, 1);
  
  var wptsProcessed = false;
  var rtesProcessed = false;
  var trksProcessed = false;
  
  // Initialize common map parts.
  map = gmapCommon();
  
  // Aha!
  GEvent.addListener(map, 'click', function(overlay, point) {
    if (overlay) {
    } else if (point) {
    }
  });
  
  // Request the XML file (GPX) using Google's XMLHTTP stuff, could use Prototype?
  var request = GXmlHttp.create();
  var URL = "http://" + window.location.hostname + "/gpx.php?points=1&pointType=waterfall";
  // alert(URL);
  request.open("GET", URL, true);
  
  request.onreadystatechange = function() {
    if (request.readyState == 4) {
  		var gpxDoc = request.responseXML;
  		if( !gpxDoc ) {
        alert("Could not load GPX document " + URL);
  		} else if( !gpxDoc.documentElement ) {
  			alert("Document " + URL + "\nwas not recognized by the XML loader");
  		} else if( gpxDoc.documentElement.tagName != 'gpx' ) {
  			alert("This does not appear to be a GPX file.");
  		} else { // This does appear to be a GPX document

  			map.setCenter(new GLatLng(35.8005, -82.4770), 8, G_PHYSICAL_MAP);

        var boundsForZoomLevel = new GLatLngBounds();
  			
        // ***************************************************
        // Process waypoints (<wpt> tags)
        // ***************************************************
  			var wpt;
  			wpt = gpxDoc.documentElement.getElementsByTagName("wpt")
  			if(wpt.length > 0) {
  			  wptsProcessed = true;
  			  sidebarHTML += '<input type="checkbox" onClick="javascript:toggleMarkers()" checked> Waypoint Markers<br>';
  				for (var i = 0; i < wpt.length; i++) {
            wptLon = parseFloat(wpt[i].getAttribute("lon"));
            wptLat = parseFloat(wpt[i].getAttribute("lat"));
  					point = new GPoint(wptLon,wptLat);
  					latlng = new GLatLng(wptLat, wptLon);
            boundsForZoomLevel.extend(latlng);
            
  					// Possible extensions:
  					// -- pointid
  					// -- photosUrl
  					// -- hikeUrl
  					
  					// Grab the ID
  					var pointid = '';
  					element = wpt[i].getElementsByTagName("pointid");
  					if( element.length ) {
  						pointid = element[0].firstChild.nodeValue;
  					}
  					
  					var tabs = new Array();
  					
  					// Tab 1
  					var tab1label = "General";
  					var tab1html = '<div class="mapTab">';
  					tphoto = "";
            tname = "";
  					tdesc = "";
  					
  					// Photo and Thumbnail
  					element = wpt[i].getElementsByTagName("photo");
  					if( element.length ) {
  						tphoto = element[0].firstChild.nodeValue;
  						tab1html += '<div style="float:right; margin-left: 5px;">' +
                '<a href="' + tphoto + 
                '" rel="lytebox" onclick="myLytebox.start(this, false); return false;">';
              
              element = wpt[i].getElementsByTagName("thumb");
    					if( element.length ) {
    						tthumb = element[0].firstChild.nodeValue;
                tab1html += '<img src="' +
                tthumb + '" style="border:1px solid black;"></a></div>';
              } // If there is a thumb
            } // If there is a photo
            
            var permalink = '';
            
            // name
  					element = wpt[i].getElementsByTagName("name");
  					if( element.length ) {
  					  tname = element[0].firstChild.nodeValue;
              // Permalink
              var urlName = tname.replace('/\s/','_');
  					  permalink = 'http://northcarolinawaterfalls.info/waterfall/' +
  					    pointid + '/' + urlName;
  						tab1html += '<h2>' + tname + '</h2>';
  					}
  					
  					// desc
  					element = wpt[i].getElementsByTagName("desc");
  					if( element.length) {
  						tdesc = element[0].firstChild.nodeValue;
  						tab1html += '<p>' + tdesc + '</p>' +
  						  '<p><a href="' + permalink +
  						  '">View this waterfall\'s full page...</a></p>';
  					}
  					
  					tab1html += '</div>';

  					var tab1 = new GInfoWindowTab(tab1label,tab1html);
  					tabs.push(tab1);

  					// Tab 2
  					var tab2label = "Stats";
  					var tab2html = "";
            theight = "";
            telev = "";
            tlandowner = "";
            
  					// Build a stats list
  					tab2html += '<div class="mapTab"><ul>';
  					
  					// Height
  					element = wpt[i].getElementsByTagName("height");
  					if( element.length ) {
  						if(element[0].firstChild){
  							theight = element[0].firstChild.nodeValue;
  							tab2html += '<li><strong>Height:</strong> ' + theight + '</li>';
  						}
  					}
  					
  					// Elevation
  					element = wpt[i].getElementsByTagName("ele");
  					if( element.length) {
  						if( element[0].firstChild) { //Fix for <ele/>
	  						telev = element[0].firstChild.nodeValue;
	  						tab2html += '<li><strong>Base Elevation:</strong> ' + telev + ' ft</li>';
	  					}
  					}

  					// Landowner
  					element = wpt[i].getElementsByTagName("landowner");
  					if( element.length ) {
  						if(element[0].firstChild){
  							tlandowner = element[0].firstChild.nodeValue;
  						tab2html += '<li><strong>Landowner:</strong> ' + tlandowner + '</li>';
  						}
  					}
  					
  					// Coordinates
  					tab2html += '<li><strong>Coordinates:</strong> ' + Math.round(wptLat * 1000000)/1000000 + 
  					            ', ' + Math.round(wptLon* 1000000)/1000000 + '</li>';
  					
  					tab2html += '</ul><p>Location is approximate.</p></div>';

  					var tab2 = new GInfoWindowTab(tab2label,tab2html);
  					tabs.push(tab2);
  					
  					// Tab 3
  					var directionsEle = wpt[i].getElementsByTagName("directions");
  					var trailDirectionsEle = wpt[i].getElementsByTagName("trailDirections");

  					if( directionsEle.length || trailDirectionsEle.length ) {
    					var tab3label = "Directions";
    					var tab3html = '<div class="mapTab">';
    					if( directionsEle.length ) {
                tdirections = "";
    						tdirections = directionsEle[0].firstChild.nodeValue;
    						tab3html += '<h2>Driving</h2>' +
    						            '<p>' + tdirections + '</p>';
    					}
    					if( trailDirectionsEle.length ) {
                tTrailDirections = "";
    						tTrailDirections = trailDirectionsEle[0].firstChild.nodeValue;
    						tab3html += '<h2>Trail</h2>' +
    						            '<p>' + tTrailDirections + '</p>';
    					}
    					tab3html += '</div>';
    					var tab3 = new GInfoWindowTab(tab3label,tab3html);
  						tabs.push(tab3);
  					}

  					// Tab 4
  					var hikeUrlEle = wpt[i].getElementsByTagName("hikeUrl");
  					var bikeUrlEle = wpt[i].getElementsByTagName("bikeUrl");
  					var otherUrlEle = wpt[i].getElementsByTagName("otherUrl");
  					
  					if( hikeUrlEle.length || bikeUrlEle.length || otherUrlEle.length )
  					{
    					var tab4label = "Links";
    					var tab4html = '<div class="mapTab"><ul>';
    					thikeurl = "";
    					tbikeurl = "";
    					totherurl = "";
  					  if( hikeUrlEle.length ) {
    						thikeurl = hikeUrlEle[0].firstChild.nodeValue;
    						tab4html += '<li><a href="' + 
                  thikeurl + '" target="_blank">Hike to This Waterfall</a></li>';
  					  }
  					  if( bikeUrlEle.length ) {
    						tbikeurl = bikeUrlEle[0].firstChild.nodeValue;
    						tab4html += '<li><a href="' +
                  tbikeurl + '" target="_blank">Mountain Bike Ride to This Waterfall</a></li>';
    					}
    					if( otherUrlEle.length ) {
    						totherurl = otherUrlEle[0].firstChild.nodeValue;
    						tab4html += '<li><a href="' + 
                  totherurl + '" target="_blank">More Information About This Waterfall</a></li>';
    					}
  					  tab4html += "</ul></div>";
  					  var tab4 = new GInfoWindowTab(tab4label,tab4html);
  					  tabs.push(tab4);
  					}
  					
  					// Determine map symbol based on <type></type> or <icon> tag
  					myicon = blue_pin;
  					type = wpt[i].getElementsByTagName("type");
  					createMarker(map, point, tabs, myicon, pointid);
  				}
  		  } // If this point has something in it

  			wpt = [];
  			// End processing waypoints
  			// Open the InfoWindow for the point in the URL if there is one
  			if(typeof(openPointId) != 'undefined'){
          myclick(openPointId);
          $('toolbox').hide();
        }
  
        // ***************************************************
        // Process routes (<rte> tags)
        // ***************************************************
  			tname = "";
        var rte;
        var rteID = 1;
        var rtename = "";
        var rtedesc = "";
  			rte = gpxDoc.documentElement.getElementsByTagName("rte");
  			if (rte.length > 0) {
  			  rtesProcessed = true;
  			  sidebarHTML += '<h4>Routes</h4>';
  			  rtePolylines = [];
  				// Process each route

  				for (var i = 0; i < rte.length; i++) {
  				  tcolor="#4012FE";
    				twidth=6;
    				topacity=.7;
  					// Routes don't have segments, but there can be multiple ones.
  					// Ignore those that don't have any <rtept> tags
            var rtept = rte[i].getElementsByTagName("rtept");
            if(rtept.length > 0){
            
    					// Extract <name></name> tag
    					rtename = "Route " + i; // Assign a default route name
    					element = rte[i].getElementsByTagName("name");
    					if( element.length ) {
    					  // But if route name is in the file. use it instead
    						if( element[0].firstChild ) {
    							rtename = element[0].firstChild.nodeValue;
    						}
    					}

    					// Extract <desc></desc> tag
    					element = rte[i].getElementsByTagName("desc");
    					if( element.length ) {
    						if( element[0].firstChild ) {
    							rtedesc = element[0].firstChild.nodeValue;
    						}
    					}

    					// Process each point of each route, string 
    					// them into a single polyline
  
    					points = [];
    					for (var k = 0; k < rtept.length; k++) {
    						points.push(new GPoint(
    							parseFloat(rtept[k].getAttribute("lon")),
    							parseFloat(rtept[k].getAttribute("lat"))));
    						}
    					rteOverlay = new GPolyline(points, tcolor, twidth, topacity);
    					rtePolylines[rteID] = rteOverlay;
    					map.addOverlay(rteOverlay);
    					// Only bother setting bounds to this route if no waypoints
    					// Based on jocassee.gpx - also ignore routes with no points
    					if(!wptsProcessed) {
      					rteBounds = rteOverlay.getBounds();
      					map.setCenter(rteBounds.getCenter(),
                              map.getBoundsZoomLevel(rteBounds),
                              G_PHYSICAL_MAP);
              }
              if(tname == ""){tname = "Route " + i;}
      				//map.addOverlay(rtePolylines[i]);
              sidebarHTML += '<p><input type="checkbox" ' + 
                             'onClick="javascript:toggleRoute(rtePolylines[' + rteID +
                             '])" checked><strong>' + rtename + '</strong><br>' +
                             rtedesc + '</p>';
              rteID++;
    				} // End if more than one <rtept> tag
          }
        rte = [];
  			} // End processing routes



        // ***************************************************
        // Process tracks (<trk> tags)
        // ***************************************************
        
  			var trk;               // Array containing all <trk></trk> tags in the document
  			var trkPosition;       // Stores the current <trk> tag's position in trk
  			var trkseg;            // Array containing all <trkseg></trkseg> tags in the current track
  			var trksegPosition;    // Counter for the # of segments in this track
  			var segmentsForTrack;  // Array, one element for each track, containing segments
  			var segments;          // Array containing segment ID's in each particular track
  			var segmentID = 1;     // Int, id of the current segment
  			var segPoints;         // Array, containing all the GPoints (lat/lon pairs) for this segment
  			var trkpt;             // Array containing all <trkpt> tags in this segment
  			var trkptPosition;     // Counter for the # of track points in this segment
  			                      
  			var trkName;           // Object which contains the current track
  			var trkNameStr;        // String to hold the name of each track
  			var trkDesc;           // Object which contains the current track
  			var trkDescStr;        // String to hold the name of each track
  			
  			boundsForTrackZoom = new GLatLngBounds();
  			
        trk = gpxDoc.documentElement.getElementsByTagName("trk");
  			if (trk.length > 0) {
  			  trksProcessed = true;
  			  sidebarHTML += '<h4>Tracks</h4>';
  				segmentPolylines = []; // Storing all segments in one array
          // Loop through each <trk></trk> tag in the trk array
  				for (trkPosition = 0; trkPosition < trk.length; trkPosition++) {
  					tcolor="#7D0000";
  					twidth=4;
  					topacity=.7;
  					trackSegmentHTML = "";
  
  					// Extract <name></name> tag for the track itself
  					trkNameStr = "";
  					trkName = trk[trkPosition].getElementsByTagName("name");
  					if( trkName.length ) {
  						if( trkName[0].firstChild ) {
  							trkNameStr = trkName[0].firstChild.nodeValue;
							}
						}
						
  					// Extract <desc></desc> tag for the track itself
  					trkDescStr = "";
  					trkDesc = trk[trkPosition].getElementsByTagName("desc");
  					if( trkDesc.length ) {
  						if( trkDesc[0].firstChild ) {
  							trkDescStr = trkDesc[0].firstChild.nodeValue;
							}
						}
						  						
  					// Get each track segment
  					trkseg = trk[trkPosition].getElementsByTagName("trkseg");
  					if(trkseg.length > 0){
              segmentHTML = "";
              for (trksegPosition = 0; trksegPosition < trkseg.length; trksegPosition++){
                segPoints = [];
                
                // Get each point
      					trkpt = trkseg[trksegPosition].getElementsByTagName("trkpt");
      					for (trkptPosition = 0; trkptPosition < trkpt.length; trkptPosition++) {
      					     trkptLat = parseFloat(trkpt[trkptPosition].getAttribute("lat"));
      					     trkptLon = parseFloat(trkpt[trkptPosition].getAttribute("lon"));
      					     trkptLatLng = new GLatLng(trkptLat,trkptLon);
      					     boundsForTrackZoom.extend(trkptLatLng);
      						   segPoints.push(new GPoint(trkptLon,trkptLat));
      						}
      					segmentPolylines[segmentID] = new GPolyline(segPoints, tcolor, twidth, topacity);
      					map.addOverlay(segmentPolylines[segmentID]);
      					segmentHTML += '<input type="checkbox" ' + 
                               'onClick="javascript:toggleSegment(segmentPolylines[' + segmentID + '])" checked>' +
                               'Segment ' + (trksegPosition + 1) + '<br>';
      					segmentID++;
              }
            trackSegmentHTML += segmentHTML;
            } // End if there were some track segments
            
            if(trkNameStr == "" && trkDescStr == ""){
              trackHTML = '<strong>Track ' + (trkPosition + 1) + '</strong><br>' + trackSegmentHTML;
            } else {
              trackHTML = '<strong>' + trkNameStr + '</strong><br>' + trkDescStr + '<br>' + trackSegmentHTML;
            }
             
            sidebarHTML += trackHTML;
  					// Only bother setting bounds to this track if no waypoints or routes
  					// I think this is broken now,  because getBounds() works on a single
  					// polyline - not a collection of polylines. May need to expand a
  					// bounding box instead and use it to zoom and center when only
  					// track(s) is(are) present
  					if(!rtesProcessed && !wptsProcessed && segmentPolylines.length > 0) {
    					map.setCenter(boundsForTrackZoom.getCenter(),
                            map.getBoundsZoomLevel(boundsForTrackZoom),
                            G_PHYSICAL_MAP);
            }
  					segPoints = [];
  				}

  				trk = [];
  				
  			} // End processing tracks
  			
  			// Indicate we're done.
  			$('tbstatus').update();
  			
			} // gpxDoc
			
      if(!wptsProcessed && !rtesProcessed && !trksProcessed){
        alert("No waypoints, routes, or tracks were found.");
        sidebarHTML = '';
      }
      // document.getElementById("routeLayers").innerHTML = sidebarHTML;
		} // readyState
  } // function
  request.send(null);
} // End load and parse GPX file
