//
//  Adds link to generate LOC file containing all waypoints on geocache page.
//  (C) Copyright 2008-2010 James Inge.  Licensed under the MIT License.
//
//  v1.04	Fixed for yet more changes to geocaching.com.  Also added better error 
//		handling, more reliable parsing, and faster skipping of pages without
//		extra waypoints.  LOC link now appears above the waypoint table.
//  v1.03	Fixed for more changes to geocaching.com
//  v1.02	Fixed for changes to geocaching.com
//  v0.01 	Initial version.
//
// ==UserScript==
// @name	Geocaching.com Additional Waypoints LOC Link
// @namespace	http://inge.org.uk/userscripts
// @description	Adds a link to generate a LOC file containing details of any additional waypoints listed on the geocache page.
// @include	http://www.geocaching.com/seek/cache_details.aspx*
// @license	MIT License; http://www.opensource.org/licenses/mit-license.php
// ==/UserScript==

(function() {
    function addWPLink() {
	var i=0, j=0, cells;

	// Find Additional Waypoints heading
	var dest = document.getElementById('ctl00_ContentBody_WaypointsInfo');

	// Additional waypoints should only be present if the heading is also there. If they are, the script's link gets added to the heading,
	// otherwise, it exits quietly.

	if( dest ) {
		// Snapshot to select all available waypoint info
		var rows = document.evaluate("//img[@alt='available']/../..", document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
		if( rows.snapshotLength > 0 ) {
			var loc = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<loc version=\"1.0\" src=\"Groundspeak\">\n";
			for( i = 0; i < rows.snapshotLength; i++ ) {
				cells = document.evaluate("td", rows.snapshotItem(i), null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
				if( cells.snapshotLength != 8 ) {
					errorMsg( "Wrong number of waypoint info cells (" + cells.snapshotLength + ").");
				} else {
					loc += "<waypoint>\n\t<name id=\"" + stripHTML(cells.snapshotItem(4).innerHTML);
					loc += "\"><![CDATA[" + stripHTML(cells.snapshotItem(5).innerHTML) + "]]></name>\n";
					var coords = stripPadding(cells.snapshotItem(6).innerHTML);
					loc += "\t<coord lat=\"" + getLat(coords) + "\" lon=\"" + getLon(coords) + "\"/>\n";
					loc += "\t<type>Geocache</type>\n";
					loc += "\t<link text=\"Waypoint details\">" + getURL(cells.snapshotItem(5)) + "</link>\n";
					loc += "</waypoint>\n";
				}
			}
			loc += "</loc>\n";
			dest.innerHTML += " <a title=\"Click to generate a LOC file from the additional coordinates.\" href=\"data:application/xml-loc," + escape(loc) +"\">[LOC]</a>";
		} // else Exit quietly - if there are waypoints, they may not have available coordinates.
	} // else Exit quietly - no additional waypoints.
    }

    function stripHTML( txt ) {
	var t = txt.slice(txt.search('>')+1);
	t = t.slice(0,t.search('</'));
	return stripPadding(t);
    }

    function getURL( cell ) {
	var link = document.evaluate("a", cell, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
	if( link.snapshotLength == 1 ) {
		var longurl = link.snapshotItem(0).href;
		return longurl.slice(0,longurl.indexOf('&'));
	} else {
		return "http://www.geocaching.com/seek/";
	}
    }

    function stripPadding( txt ) {
        return txt.replace( /&nbsp;/, " ").replace( /^\s+/, "" ).replace(/\s+$/, "" );
    }

    function getLat( txt ) {
	var deg = 0, min = 0;
	if( txt.length != 26 ) {
		/****
		 * This relies on the coordinate being in the format: N 50' 54.344 W 001' 24.110
		 ****/
		errorMsg( "Unexpected coordinate string length (" + txt.length + "): " + txt );
		return 0;
	} else {
		deg = txt.slice(2,4);
		/* Force text to number */
		deg *= 1;
		min = txt.slice(6,12);
		min /= 60;
		deg += min;
		if( txt.indexOf('N') == -1 ) {
			return 0 - deg;
		} else {
			return deg;
		}
	}
    }

    function getLon( txt ) {
	var deg = 0, min = 0;
	if( txt.length != 26 ) {
		/****
		 * This relies on the coordinate being in the format: N 50' 54.344 W 001' 24.110
		 ****/
		errorMsg( "Unexpected coordinate string length (" + txt.length + "): " + txt );
		return 0;
	} else {
		deg = txt.slice(15,18);
		/* Force text to number */
		deg *= 1;
		min = txt.slice(20);
		min /= 60;
		deg += min;
		if( txt.indexOf('W') == -1 ) {
			return deg;
		} else {
			return 0 - deg;
		}
	}
    }

    function errorMsg ( msg ) {
	alert( "Greasemonkey script 'Geocaching.com Additional Waypoints LOC Link' reported the error '" + msg +"'\n\nMost likely this is caused by a change in the Geocaching.com web page layout. Check userscripts.org to see if a new version of the script is available - in the meantime you may wish to disable the script via Greasemonkey, to stop this message popping up.");
    }

    addWPLink();
})();

