/*
Geocaching True Totals - v1.3 2006-04-04
(c) 2006, Prime Suspect Software

Greasemonkey user script: see http://greasemonkey.mozdev.org

Function:
 Copies 'Show All Logs' link above the logs. When all logs are 
 displayed, a breakdown of totals by log type is shown
 above the logs.
 
 In the upper left, a summary of all the logs the user has posted
 to that cache is shown. 
 
Usage:
 When link to show all logs is clicked, after loading, the page 
 will be repositioned to the start of the logs. 'Show All Logs' 
 link will be replaced by the type totals. If there are 5 or fewer 
 logs for a cache, the totals by type will automatically be show.
 In the user's log summary (in the upper right of the page), 
 clicking on a log's date will reposition the page to that log.

Revision History:

v1.3 - Add support for Moved Coordinates log type.

v1.2 - Add support for Needs Maintenance and Maintenance Performed
 log types.

v1.1 - Added summary of logs posted to that cache by the user.

v1.0 - Initial release

*/

// ==UserScript==
// @name           GC True Totals
// @namespace      http://gmscripts.locusprime.net/
// @description    (v1.3) Shows breakdown of totals by log type, plus summary of user's logs.
// @include        http://www.geocaching.com/seek/cache_details.aspx?*
// ==/UserScript==

(function() {

	var SpanData = '';
	var ImgCount;
	var ImgFile = new Array();
	var ImgDesc = new Array();
	var LogList = new Array();
	var userName = '';

	//  Check URL. If Printer Frindly mode, exit script.
	if (UrlParm('pf') == 'y') {return}

	//  If specific number of logs set to be displayed, exit script.
	if (UrlParm('numlogs') != '') {return}

	//  See if 'MoreLogs' link is present.
	var e_LogWarning = document.getElementById("LogWarning");
	var e_MoreLogs = document.getElementById("MoreLogs");
	
	if (e_MoreLogs) {
		
		// Add anchor tag to link, to position page at start of logs.
		var e_WarnURL = e_MoreLogs.childNodes[0].childNodes[0].childNodes[1];
		e_WarnURL.href += '#NumVisits';

		//  Copy 'more logs' link above the logs.
		dup_MoreLogs = e_MoreLogs.cloneNode(true)
		var LogWarnBR = document.createElement("br");
		e_LogWarning.parentNode.insertBefore(LogWarnBR, e_LogWarning.nextSibling);
		LogWarnBR.parentNode.insertBefore(dup_MoreLogs, LogWarnBR.nextSibling);
		

	} else {

		//  Get user name.
		var e_lnkLoginName = document.getElementById("Header1_lnkLoginName");
		if (e_lnkLoginName) {
			userName = e_lnkLoginName.firstChild.firstChild.data;
		}

		//  Log types and image icons to be counted.
		ImgDesc[ 0] = 'Will Attend';
		ImgFile[ 0] = 'icon_rsvp.gif';
		ImgDesc[ 1] = 'Attended';
		ImgFile[ 1] = 'icon_attended.gif';
		ImgDesc[ 2] = 'Webcam Photo Taken';          
		ImgFile[ 2] = 'icon_camera.gif';      
		ImgDesc[ 3] = 'Found Cache';          
		ImgFile[ 3] = 'icon_smile.gif';       
		ImgDesc[ 4] = 'Did Not Find';         
		ImgFile[ 4] = 'icon_sad.gif';         
		ImgDesc[ 5] = 'Note';                 
		ImgFile[ 5] = 'icon_note.gif';        
		ImgDesc[ 6] = 'Review Note';          
		ImgFile[ 6] = 'big_smile.gif';        
		ImgDesc[ 7] = 'Retraction';           
		ImgFile[ 7] = 'icon_redlight.gif';    
		ImgDesc[ 8] = 'Published';            
		ImgFile[ 8] = 'icon_greenlight.gif';  
		ImgDesc[ 9] = 'Disabled';             
		ImgFile[ 9] = 'icon_disabled.gif';    
		ImgDesc[10] = 'Enabled';              
		ImgFile[10] = 'icon_enabled.gif';     
		ImgDesc[11] = 'Performed Maintenance';             
		ImgFile[11] = 'icon_maint.gif';     
		ImgDesc[12] = 'Needs Maintenance';       
		ImgFile[12] = 'icon_needsmaint.gif';     
		ImgDesc[13] = 'Needs Archive';       
		ImgFile[13] = 'icon_remove.gif';     
		ImgDesc[14] = 'Archived/Unarchived';             
		ImgFile[14] = 'traffic_cone.gif';     
		ImgDesc[15] = 'Update Coordinates';             
		ImgFile[15] = 'coord_update.gif';     


		//  Get count of each image type. Build display string.
		for (var i = 0; i < ImgFile.length; i++) {
			ImgCount = GetCount(ImgFile[i], i)
			if (ImgCount > 0) {
				SpanData += ' &nbsp; <img src="http://www.geocaching.com/images/icons/' +
						ImgFile[i] +'" align="absmiddle" title="' + ImgDesc[i] + '">' +
						'=' + ImgCount;
			}
		}
	
		//  If display string not blank, insert into document.
		if (SpanData > '') {
			if (e_LogWarning) {
				CountSpan = document.createElement("span");
				CountSpan.innerHTML = '<br>Totals by log type:' + SpanData;
				e_LogWarning.parentNode.insertBefore(CountSpan, e_LogWarning.nextSibling);
			}
		}


		//  Get starting cell for adding data.
		var xPathSearch = "//TD[@class='charcoal_header']";
		var tdList = document.evaluate(
			xPathSearch,
			document,
			null,
			XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
			null);
		tdList.snapshotItem(0).height = '';
		var wptTD = tdList.snapshotItem(0).nextSibling.nextSibling;
		wptTD.width = 140;
		wptTD.align = 'center';
		var divTD = document.createElement("TD");
		divTD.width = 175;
		wptTD.parentNode.insertBefore(divTD, wptTD.nextSibling);
		e_LogDiv = document.createElement("div");
		e_LogDiv.style.border = 'solid 1px rgb(198,198,198)';
		e_LogDiv.style.padding = '2px';
		e_LogDiv.style.marginBottom = '4px';
		e_LogDiv.style.MozBorderRadius = '5px';
		e_LogDiv.style.backgroundColor = 'rgb(238,238,238)';
		e_LogDiv.align = 'left';
		divTD.appendChild(e_LogDiv);

		//  Add list of user's logs to page.
		if (LogList.length > 0) {
			//  Add message indicating total number of logs.
			var s = 's';
			if (LogList.length == 1) {s = ''}
			var logsMsg = document.createTextNode(LogList.length + " log" + s + " posted by you:")
			e_LogDiv.appendChild(logsMsg);
			//  Get URL, and strip off any anchor tag.
			thisURL = document.location + "";
			thisURL = thisURL.replace(/^(.*?)#.*$/, '$1');			
			//  Sort users logs in reverse entry order.
			LogList.sort().reverse();
			for (var i = 0; i < LogList.length; i++) {
				//  Extract data fields for each user's log.
				var LogFlds = LogList[i].split('\t');
				var logID = LogFlds[0] - 0;
				var typeID = LogFlds[1] - 0;
				var logDate = LogFlds[2].replace(/^\s*(.*?)\s+by\s*$/, '$1');
				//  Add data to page.
				var e_LogTypeImg = document.createElement("img");
				e_LogTypeImg.src = "http://www.geocaching.com/images/icons/" + 
						ImgFile[typeID];
				e_LogTypeImg.title = ImgDesc[typeID];
				e_LogTypeImg.width = 16;
				e_LogTypeImg.height = 16;
				e_LogTypeImg.align = 'absmiddle';
				e_LogDiv.appendChild(document.createElement("br"));
				e_LogDiv.appendChild(e_LogTypeImg);
				e_LogDiv.appendChild(document.createTextNode(" "));
				var e_LogDateLink = document.createElement("a");
				e_LogDateLink.href = thisURL + "#" + logID;
				e_LogDateLink.title = 'Click to postion to this log';
				e_LogDateLink.appendChild(document.createTextNode(logDate));
				e_LogDiv.appendChild(e_LogDateLink);
			}
		} else {
			if (userName.length > 0) {
				var msgText = "No logs posted by you.";
			} else {
				msgText = "You are not logged in.";
			}
			logsMsg = document.createTextNode(msgText);
			e_LogDiv.appendChild(logsMsg);
		}
		
	}
	
	//  Reposition to log anchor.
	var docloc = document.location + '';
	if (docloc.search(/#NumVisits$/) >= 0) {
		document.location = document.location;
	}
		



// ---------------------------------- Functions ---------------------------------- //


	//  Returns a URL parameter.
	function UrlParm(SeekParm) {
		var RegRslt, RtnVal = '';
		var PageUrl = document.location + '';
		var ParmString = PageUrl.substring(PageUrl.indexOf('?') + 1);
		var RegEx1 = new RegExp('(^|&)' + SeekParm + '=(.*?)(&|#|$)');
		RegRslt = RegEx1.exec(ParmString);
		if (RegRslt) {
			RtnVal = RegRslt[2];
		}
		return RtnVal;
	}


	//  Returns number of images.
	function GetCount(img, imgID) {
		var ic = 0;
		//  Build search path.
		var xPathSearch = "//img[@src='http://www.geocaching.com/images/icons/" + img + "']";
		//  Execute xpath query to get a collection of images.
		var ImgList = document.evaluate(
			xPathSearch,
			document,
			null,
			XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,
			null);
		//  If not the smile icon, just get image collection count.
		if (img != 'icon_smile.gif') {
			var ic = ImgList.snapshotLength;
			for (var i = 0; i < ic; i++) {
				var logOwner = ImgList.snapshotItem(i).parentNode.childNodes[3].firstChild.data;
				if (logOwner == userName) {
					var logDate = ImgList.snapshotItem(i).parentNode.childNodes[1].data;
					var logID = ImgList.snapshotItem(i).parentNode.childNodes[2].name;
					logID = Right('000000000000' + logID, 12);
					LogList.push(logID + '\t' + imgID + '\t' + logDate);
				}
			}
		//  Smile icon can also be used within a log, so have to check each one.
		} else {
			for (var i = 0; i < ImgList.snapshotLength; i++) {
				//  Only icons that are a child of a STRONG node are log types.
				if (ImgList.snapshotItem(i).parentNode.nodeName == 'STRONG') {
					var logOwner = ImgList.snapshotItem(i).parentNode.childNodes[3].firstChild.data;
					if (logOwner == userName) {
						var logDate = ImgList.snapshotItem(i).parentNode.childNodes[1].data;
						var logID = ImgList.snapshotItem(i).parentNode.childNodes[2].name;
						logID = Right('000000000000' + logID, 12);
						LogList.push(logID + '\t' + imgID + '\t' + logDate);
					}
					ic++;
				}
			}
		}
		return ic;
	}


	//  Left string function.	
	function Left(str, n){
		if (n <= 0)
			return "";
		else if (n > String(str).length)
			return str;
		else
			return String(str).substring(0,n);
	}

	
	//  Right string function.
	function Right(str, n){
	    if (n <= 0)
		return "";
	    else if (n > String(str).length)
		return str;
	    else {
		var iLen = String(str).length;
		return String(str).substring(iLen, iLen - n);
	    }
	}

})();
