/**
 * easyJS.js
 * @author philip.ward
 * @requires jQuery.js
 * @fileoverview Various functions, partly layered on jQuery, generic and hopefully usable in many different contexts.
 */

// Logging: determine whether we show popup log messages:
 
var SHOWLOGS = false;
var pwLogString = "";	//	global...

function VideoTip(someMovie, someTitle, someText) {
	
	//	Show a YouTube (or, in principle, other) video in a Walter Zorn popup.
	
	var obj = "<object width=\'425\' height=\'344\'><param name=\'movie\' value=\'http://www.youtube.com/v/" + someMovie + "&hl=en&fs=1\'></param><param name=\'allowFullScreen\' value=\'true\'></param><param name=\'allowscriptaccess\' value=\'always\'></param><embed src=\'http://www.youtube.com/v/" + someMovie + "&hl=en&fs=1\' type=\'application/x-shockwave-flash\' allowscriptaccess=\'always\' allowfullscreen=\'true\' width=\'425\' height=\'344\'></embed></object>";
	
	if (someText != "") {
		obj += "<P>" + someText;
	}
	Tip(obj, WIDTH, 0, PADDING, 10, BGCOLOR, '#E0E4FF', CLOSEBTN, 'TRUE', DURATION, 0, FOLLOWMOUSE, 'FALSE', TITLE, someTitle, TITLEFONTSIZE, '10pt', OFFSETX, -4, OFFSETY, -4, STICKY, 'true');
}

function testError (whatever) {
	
	var result = true;
	
	log("String: " + whatever);
	
	try {
		throw new TypeError("This is not a string");
		log("No error found");
	} catch (e) {
		log("File: " + e.fileName);
		log("Line: " + e.lineNumber);
		log("Stack: " + e.stack);		
	} finally {
		report();
	}
}

function updateRow(someString, someTable) { //	Updates a single row, identified by ID in the resultsTable. If no such row exists, the row is appended to the table.

/*
 * Arguments: someString, being a string containing an ID string followed by a colon followed by the HTML text (should normally
 * contain <TD>...</TD>) to be inserted into the row or appended as a row to the table.
 * 
 * For example, updateRow("12:<TD>Phil</TD><TD>Ward</TD>", "resultsTable") will insert the HTML text 
 * "<TD>Phil</TD><TD>Ward</TD>" into the row with ID TR_12 in the table with ID "resultsTable".
 */
	
	var q = someString.indexOf(":");
	var objId = someString.substr(0, q);
	q++;
	var inHtml = someString.substr(q);
	
	if ($("#TR_" + objId).length > 0) {
		$("#TR_" + objId).html(inHtml);
	} else {
		$("#resultsTable").children('tbody').append("<TR>" + inHtml + "</TR>");
	}
	
	return;	
}

function checkFilled(thing) { // Check a form field is not empty

	if (thing.value == "") {
		alert("The '" + thing.name + "' field cannot be blank.");
		fieldFocus(thing);
	}
	return;
}

function checkEmail(thing) { // Check value of a form field is an email address

	var foo = thing.value;
	foo = foo.toLowerCase();
	
	if (!/^[a-z0-9._%+-]+@[a-z0-9.-]+\.(?:[a-z]{2}|com|org|net|gov|biz|info|name|aero|biz|info|jobs|museum)$/.test(foo)) {
		alert("Please enter a properly formatted email address, such as john.smith@yahoo.com.")
		fieldFocus(thing);
	}
	return;
}

function checkDigit(thing) { // Check value of a form field is a single digit

	if(!/^\d$/.test(thing.value)) {
		alert("The '" + thing.name + "' field must be a single digit from 1 to 9.");
		fieldFocus(thing);
	}
	return;
}

function checkAnyOf(thing, allowedValues) { // Check value of a form field is one of a list of allowed values

	var av_array = allowedValues.split('#');
	var foo = allowedValues.toUpperCase();
	var av_copy = foo.split('#');
	var foo = thing.value.toUpperCase();
	var av_actual = foo.split(",");	
	var ar = 0;
	var ac = 0;	
	var fv = "";	// 	Final value
		
	for (ar=0;ar<av_array.length; ar++) {
		
		for (ac=0;ac<av_actual.length; ac++) {
			
			if (av_actual[ac].substr(0,1) == av_copy[ar].substr(0,1)) {
				
				if (fv != "") {
					fv = fv + ", ";
				}
				fv = fv + av_array[ar];
			}
		}
	}
	
	if (fv == "") {
		alert("Illegal value for " + thing.name + "! Can be any of " + av_array + " or initial letters.");
		fieldFocus(thing);
	} else {
		thing.value = fv;
	}
	return;
}

function checkNumeric(thing) { // Check value of a form field is a positive integer

	if(!/^\d+$/.test(thing.value)) {
		
		if (thing.value != "") {
			alert("The '" + thing.name + "' field must be numeric.");
			fieldFocus(thing);
		}
	}
	return;
}

function checkPassword(thing) { // Check a password has a legal value 
	
	//	Newly-changed passwords must contain at least one uppercase letter, one lowercase letter, and one numeral,
	//	and must be between 8 and 15 characters long.
	
	var pwd = thing.value;
	alert(pwd);
	var lgth = pwd.length;
	
	if (/[A-Z]/.test(pwd)) {
		
		if (/[a-z]/.test(pwd)) {
			
			if (/[0-9]/.test(pwd)) {
				
				if (lgth > 7) {
					
					if (lgth < 16) {
						
						//	Ask user to re-enter the password
						var np = confirm("Please re-enter your password.");
						
						if (np != pwd) {
							alert("Password values do not match.");
						} else {
							return;
						}
					}
				}
			}
		}
	} else {
		alert("Passwords must contain at keast one upper-case letter (A-Z), at least one lower-case letter (a-z), and at least one numeric digit (0-9), and must be between 8 and 15 characters long.")
	}
	
	fieldFocus(thing);
	return;
}

function checkDate(thing) { // Check value of a form field is a date

	if(!/^((19|20)[0789][0-9]-(0[1-9]|1[0-2])-([0-2]\d|3[01])|(19|20)[0789][0-9]-(0[1-9]|1[0-2])|(19|20)[0789][0-9]|u|t)$/.test(thing.value)) {
		alert("The '" + thing.name + "' field must be a date in the form yyyy-mm-dd, e.g. '1985-08-25'. If the exact date is not known, use yyyy-mm, e.g. '1985-08'; if only the year is known, enter it using yyyy, e.g. '1985'. If not even the year is known, write 'u'. For today's date, write 't'.");
		fieldFocus(thing);
		return;
	}
	
	if(thing.value == 'u') {
		thing.value = 'Unknown';
	}
	
	if(thing.value == 't') {
		var now = new Date();
		var ds = now.getFullYear() + "-";
		var mm = now.getMonth() + 1;
		
		if (mm < 10) {
			ds = ds + "0" + mm + "-";
		} else {
			ds = ds + mm + "-";
		}
		mm = now.getDate();
		
		if (mm < 10) {
			ds = ds + "0" + mm;
		} else {
			ds = ds + mm;
		}
		thing.value = ds;
	}
	return;
}

function checkDuration(thing) { // Check value of a form field is a duration
	
	/* Permitted formats:
	 * 
	 * 	h:mm:ss
	 * simple number of seconds
	 * mm:ss
	 * simple number of minutes
	 * 
	 */
	
	var hh;
	var s;
	var mm;
	
	var tots;
	
		if (/^\d:([0-5]|)\d:([0-5]|)\d$/.test(thing.value)) {	//	h.mm.ss format
//			alert("h:mm:ss format");
			s = thing.value;
			var time_array = s.split(":");
			log(time_array);
			s = (3600*time_array[0]) + (60*time_array[1])+parseInt(time_array[2]);
			log(s + " seconds");
			
//			return;	//	No need to change display
		} else {
			
			if (/^[0-9]{1,3}[mM]$/.test(thing.value)) {	//	mmM format (number of minutes with M or m suffix
//				alert("nnnM format");
				mm = thing.value.length-1;
				mm = thing.value.substr(0, mm);
				s = mm * 60;
			} else {
				
				if (/^[0-9]{1,5}$/.test(thing.value)) {	//	simple number of seconds
//					alert("number of seconds format");
					s = thing.value;
				} else {
					
					if (/^[0-9]{1,3}:([0-5]|)\d$/.test(thing.value)) {	//	mmm:ss format
//						alert("mmm:ss format");
						var d = thing.value.indexOf(":");
						mm = thing.value.substr(0, d);
						mm = mm * 2;
						s = thing.value.substr(d+1);
						s = s * 2;
						s = s / 2 + 30 * mm;		
					} else {
						
						alert("*** Duration can be entered either in the form h:mm:ss, for example 2:35:16 for 2 hours and 35 minutes and 16 seconds or 0:06 for six seconds, or as a simple number of seconds (from 1 to 99999). You can also use the formats m:ss, or e.g. 29m for 29 minutes.");
						fieldFocus(thing);
						return;
					}
				}
			}
		}
		
//		alert(s);

		tots = s;
		
		mm = Math.floor(s/60);
		s = s - 60 * mm;
		if (s < 10) s = "0" + s;
		hh = Math.floor(mm/60);
		mm = mm - 60 * hh;
		if (mm < 10) mm = "0" + mm;
		
		thing.value = hh + ":" + mm + ":" + s + "   ( " + tots + " sec)";
		
		return;
}

function fieldFocus(whatever) { // Focus a field in a popup (or anywhere, for that matter)

	var myId = whatever.name;
	var doString = 'document.forms.easyForm.' + myId + '.focus(); document.forms.easyForm.' + myId + '.select()';
	setTimeout(doString, 100);
	return;
}

function tr (alt, neu, whatever) { // Partially simulates the perl s function, replacing all instances of alt by neu in the string. 
		
	var my_array = whatever.split(alt);
	var answer = my_array[0];
	var i;
	
	for(i=1;i<my_array.length;i++) {
		answer = answer + neu + my_array[i];
	}
	
	return answer;
	
}

function timeStamp() { // Returns timestamp of the form hh:mm:ss.mmm
  
    var curTime = new Date();
    
    var q1 = curTime.getHours();    
    if (q1 < 10) {q1 = "0" + q1;}
    
    var q2 = curTime.getMinutes();
    if (q2 < 10) {q2 = "0" + q2;}

    var q3 = curTime.getSeconds();
    if (q3 < 10) {q3 = "0" + q3;}
	
	var q4 = curTime.getMilliseconds();
	
	if (q4 < 100) {
		q4 = (q4 < 10) ? "00" + q4 : "0" + q4;
	}
    
    var h = q1 + ":" + q2 + ":" + q3 + "." + q4;

    return h;
    
  }
  
function log(whatever){ //appends to current log message listing
	
	//	Identify the function which invoked the logging:
	
	var c = log.caller;
	var d;
	
	if (c == null) { //	if called from inline HTML
		d = "Script> ";
	}
	else {
		d = c.toString().substr(9);
	}
	d = d.substr(0, d.indexOf("("));
	
	var logEntry = timeStamp() + " " + d + ": " + whatever;
	
	if (window.console) {
		console.log(logEntry);
	} else {
		//window.status = logEntry;
				
		if (pwLogString != "") {
			pwLogString += "\n";
		}
		pwLogString += logEntry;		
	}
    return false;
  }
  
function report() { // displays current log message listing and empties cache.
  
    //  Dump log messages to the screen
    
	if (window.console) {
		return false;
	}
	
	if (pwLogString == "") {
		return false;
	}	
	
    if (SHOWLOGS) {alert(pwLogString)};
    pwLogString = "";
    return false;
    
  }
  
  var minf=8;
  var maxf=18;
  
function increaseFontSize(whatever) {
   var p = document.results.getElementsByTagName(whatever); // was p
   for(i=0;i<p.length;i++) {
      if(p[i].style.fontSize) {
         var s = parseInt(p[i].style.fontSize.replace("px",""));
      } else {
         var s = 12;
      }
      if(s!=maxf) {
         s += 1;
      }
      p[i].style.fontSize = s+"px"
   }
}
function decreaseFontSize(whatever) {
   var p = document.results.getElementsByTagName(whatever); // was p
   for(i=0;i<p.length;i++) {
      if(p[i].style.fontSize) {
         var s = parseInt(p[i].style.fontSize.replace("px",""));
      } else {
         var s = 12;
      }
      if(s!=minf) {
         s -= 1;
      }
      p[i].style.fontSize = s+"px"
   }  
}

function bigFont() {
	increaseFontSize('p');
	increaseFontSize('input');
	increaseFontSize('select');
	increaseFontSize('td');
	increaseFontSize('textarea');
}

function smallFont() {
	decreaseFontSize('p');
	decreaseFontSize('input');
	decreaseFontSize('select');
	decreaseFontSize('td');
	decreaseFontSize('textarea');
}

function bigTable() {
	increaseFontSize('td')
}

function smallTable() {
	decreaseFontSize('td')
}

//	Left and Right functions from http://www.devx.com/tips/Tip/15222

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

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);
    }
}

function singular(whatever) {
	
	//	may need a bit more code if unusual words e.g. "mice" come up...
	
	if (Right(whatever, 3) == "ies") {
		return whatever.replace("ies", "y");
	} else {
		return whatever.substr(0, whatever.length()-1);
	}
}

var BrowserDetect = { // Identifies browser being used
	init: function () {
		this.browser = this.searchString(this.dataBrowser) || "An unknown browser";
		this.version = this.searchVersion(navigator.userAgent)
			|| this.searchVersion(navigator.appVersion)
			|| "an unknown version";
		this.OS = this.searchString(this.dataOS) || "an unknown OS";
	},
	searchString: function (data) {
		for (var i=0;i<data.length;i++)	{
			var dataString = data[i].string;
			var dataProp = data[i].prop;
			this.versionSearchString = data[i].versionSearch || data[i].identity;
			if (dataString) {
				if (dataString.indexOf(data[i].subString) != -1)
					return data[i].identity;
			}
			else if (dataProp)
				return data[i].identity;
		}
	},
	searchVersion: function (dataString) {
		var index = dataString.indexOf(this.versionSearchString);
		if (index == -1) return;
		return parseFloat(dataString.substring(index+this.versionSearchString.length+1));
	},
	dataBrowser: [
		{ 	string: navigator.userAgent,
			subString: "OmniWeb",
			versionSearch: "OmniWeb/",
			identity: "OmniWeb"
		},
		{
			string: navigator.vendor,
			subString: "Apple",
			identity: "Safari"
		},
		{
			prop: window.opera,
			identity: "Opera"
		},
		{
			string: navigator.vendor,
			subString: "iCab",
			identity: "iCab"
		},
		{
			string: navigator.vendor,
			subString: "KDE",
			identity: "Konqueror"
		},
		{
			string: navigator.userAgent,
			subString: "Firefox",
			identity: "Firefox"
		},
		{
			string: navigator.vendor,
			subString: "Camino",
			identity: "Camino"
		},
		{		// for newer Netscapes (6+)
			string: navigator.userAgent,
			subString: "Netscape",
			identity: "Netscape"
		},
		{
			string: navigator.userAgent,
			subString: "MSIE",
			identity: "Explorer",
			versionSearch: "MSIE"
		},
		{
			string: navigator.userAgent,
			subString: "Gecko",
			identity: "Mozilla",
			versionSearch: "rv"
		},
		{ 		// for older Netscapes (4-)
			string: navigator.userAgent,
			subString: "Mozilla",
			identity: "Netscape",
			versionSearch: "Mozilla"
		}
	],
	dataOS : [
		{
			string: navigator.platform,
			subString: "Win",
			identity: "Windows"
		},
		{
			string: navigator.platform,
			subString: "Mac",
			identity: "Mac"
		},
		{
			string: navigator.platform,
			subString: "Linux",
			identity: "Linux"
		}
	]

};

BrowserDetect.init();

var globalBrowser = BrowserDetect.browser; 


