// --------------------------------------- Utility Scripts
//
// Written by all sorts of people
// October 2001 - January 2002
// Copyright 2001-2, Cognitive Arts
//
// --------------

// --------------------------------------- Token Lists

// Constants

var MID_TOKEN = ":";
var END_TOKEN = ",";
var ARRAY_TOKEN = "@";

// Public Methods

// make this case insensitive?

function setTokenListValue (list, name, value)
{
	if (validTokenType (value))
	{
		if (value && value.indexOf && value.indexOf (END_TOKEN) != -1)
			reportError ("Putting a '" + END_TOKEN + "' in a token list value is very bad: " + value);

		list = clearTokenListValue (list, name);
		
		if (list == null)
			list = makeToken (name, value);
		else
			list = list + makeToken (name, value);
		
		return list;
	}
	else
		reportError ("Setting '" + name + "' to '" + value + "' failed; '"
			+ (typeof value) + "' is not a valid variable type.");
}

function getTokenListValue (list, name)
{
	if (list != null)
	{
		var junk = findTokenListToken (list, name);
		
		if (junk != null)
		{		
			var type = junk.substr (junk.indexOf (MID_TOKEN) + 1, 1);
			var value = junk.substring (junk.indexOf (MID_TOKEN) + 3, junk.indexOf (END_TOKEN));

			if (type == "l")
				return null
			else if (type == "n")
				return parseFloat (value);
			else if (type == "b")
				return (value == "t");
			else if (type == "s")
				return value;
			else if (type == "a")
				return value.split (ARRAY_TOKEN);
			else
				reportError (type + " is not a known variable type. Occurred while getting " + name);
		}
		else
			return null;
	}
	else
		return null;
}

function findTokenListToken (list, name)
{
	if (list != null)
	{
		var index = list.indexOf (name + MID_TOKEN);
		var junk = "";
		
		if (index == -1)
			return null;
		
		if (index == 0)
			junk = list;
		
		if (index > 0) // if you're looking for name which is substring of another name
		{
			index = list.indexOf (END_TOKEN + name + MID_TOKEN);
			
			if (index == -1)
				return null;
			else
				junk = list.substring (index + 1);
		}
		
		return junk.substring (0, junk.indexOf (END_TOKEN) + 1);
	}
	else
		return null;
}

function clearTokenListValue (list, name)
{
	if (list != null)
	{
		var oldvalue = findTokenListToken (list, name);
		
		if (list.indexOf (oldvalue) == 0)
			return list.substring (oldvalue.length);
		else
			return replace (list, END_TOKEN + oldvalue, END_TOKEN);
	}
	else
		return null;
}

// Internal Methods

function validTokenType (value) 
{
	// add date

	return (typeof value == "string")
		|| (typeof value == "number")
		|| (typeof value == "boolean")
		|| (value == null)
		|| ((typeof (value) == "object") && (typeof (value.length) == "number"))
}

function makeToken (name, value)
{
	var type = "u";
	
	if (value == null)
	{
		type = "l";
		value = "l";
	}
	else if (typeof value == "boolean")
	{
		type = "b";
		
		if (value == true)
			value = "t";
		else
			value = "f";
	}
	else if (typeof value == "string")
	{
		type = "s";
	}
	else if (typeof value == "number")
	{
		type = "n";
		value = value.toString ();
	}
	else if ((typeof (value) == "object") && (typeof (value.length) == "number"))
	{
		type = "a";
		value = replace (value.toString (), ",", ARRAY_TOKEN);
	}
	
	return (name + MID_TOKEN + type + MID_TOKEN + value + END_TOKEN);
}

// --------------------------------------- Cookie Manipulation

function getCookie (name)
{
	var start = document.cookie.indexOf (name + "=");

	var len = start + name.length + 1;

	if ((!start) && (name != document.cookie.substring (0, name.length)))
		return null;

	if (start == -1)
		return null;

	var end = document.cookie.indexOf (";", len);

	if (end == -1)
		end = document.cookie.length;

	reslt = unescape (document.cookie.substring (len, end));
	reslt = reslt.replace (/\+/g, " ");

	return (reslt);
}

function setPersistentCookie (name, value)
{
    setCookie (name, value, new Date ("December 31, 2023"));
}

function setCookie (name, value, expires, path, domain, secure, escapeP)
{
	if ((name == null) || (name == ""))
		return false;
	
	// if ((navigator.appName == "Microsoft Internet Explorer") && ! navigator.cookieEnabled) fail immediately?

	if (escapeP == null)
		escapeP = true;

	var v = (escapeP ? escape (value) : value);
	
	if (v.length >= 3882) // the IE cookie size limit, by my testing
	{
		alert ("Attempt to set cookie " + name + " failed because the contents are too long:\n\n" + v);
		return false;
	}
	
	document.cookie = name + "=" + v
		+ ((expires == null) ? ""         : "; expires=" + expires.toGMTString ())
		+ ((path == null)    ? "; path=/" : "; path=" + path)
		+ ((domain == null)  ? ""         : "; domain=" + domain)
		+ ((secure == null)  ? ""         : "; secure");

	// change getCookie failed return value from null?

	if ((value != null) && (value != "") && (getCookie (name) != value))
	{
		alert ("Attempt to set cookie " + name + " failed. Please enable cookies.");
		return false;
	}
	else
		return true;
}

function expireCookie (name, path, domain)
{
	var expiration = new Date ();

	expiration.setTime (expiration.getTime () - 1);  // + 86400000 to add 1 day
	setCookie (name, null, expiration, path, domain);
}

// --------------------------------------- URL Manipulation

// Note that this returns "2" instead of "fef" for a URL like foo.cfm?z=?x=2&x=fef

function getURLParameter (name)
{
	return getParameter (location.search, name);
}

// fixed to be non-case sensitive
// needs a lot more cleaning, though -- this code is gross

function getParameter (info, name)
{
	var infolowercase = info.toString ().toLowerCase ();
	var namelowercase = name.toString ().toLowerCase ();

	var start = infolowercase.indexOf ("?" + namelowercase + "=");

	if (start == -1)
		start = infolowercase.indexOf ("&" + namelowercase + "=");
	if (start == -1)
		return (null);

	start = start + 1;

	var len = start + namelowercase.length + 1;
	var end = infolowercase.indexOf ("&", len);

	if (end == -1)
		end = infolowercase.length;

	res = unescape (info.substring (len, end));
	res = res.replace (/\+/g, " ");

	return (res);
}

// --------------------------------------- Array Methods

Array.prototype.add = function (item)
{
	this [this.length] = item;

	return this;
}

Array.prototype.remove = function (index)
{
	for (var i = index; i <= this.length - 1; i ++)
		this [i] = this [i + 1];

	this.length --;

	return this;
}

Array.prototype.shuffle = function ()
{
	var indices = new Array ();
	var temp = new Array ();

	for (var i = 0; i < this.length; i ++)
		indices [i] = i;

	for (var i = 0; i < this.length; i ++)
	{
		var randomindex = Math.floor (Math.random () * indices.length);
		
		temp [i] = this [indices [randomindex]];
		indices.remove (randomindex);
	}

	for (var i = 0; i < this.length; i ++)
		this [i] = temp [i];

	return this;
}

// --------------------------------------- Location Predicates

function localP ()
{
	return (! serverP ());
}

function serverP ()
{
	return (document.location.toString ().indexOf ("http") == 0);
}

// --------------------------------------- Text Manipulation

function trim (text)
{
    while (whitespacep (text.substring (0, 1)))
        text = text.substring (1, text.length);

    while (whitespacep (text.substring (text.length - 1, text.length)))
        text = text.substring (0, text.length - 1);

   return text;
}

function whitespacep (character)
{
	return (character == ' ' || character == '\n' || character == '\r')
}

// Netscape 4 Sucks So Bad
// From Martin Webb
// http://tech.irt.org/articles/js037/index.htm

function replace (string, text, by) // Replaces text with by in string
{
	var strLength = string.length
	var txtLength = text.length;
	
	if ((strLength == 0) || (txtLength == 0)) return string;

	var i = string.indexOf (text);
    
	if ((!i) && (text != string.substring (0, txtLength)))
		return string;
    
	if (i == -1)
		return string;

	var newstr = string.substring (0, i) + by;

	if (i + txtLength < strLength)
		newstr += replace (string.substring (i + txtLength, strLength), text, by);

	return newstr;
}

// --------------------------------------- Debug Tools

function showcurrentstate ()
{
	alert (replace (userstate, END_TOKEN, "\n"));
}

var debugtrace = "";
var debugwindow = null;

var DIVIDER = '\n-------------------------------------------------------------';

function reportdebug (message)
{
	message = message + DIVIDER;
	if (debugtrace != "")
		message = "\n" + message;
	
	debugtrace += message;  // truncate by length?
	
	if (debugwindow && ! debugwindow.closed)
		debugwindow.document.getElementById ("trace").value += message;
}

function showdebugtrace ()
{
	debugwindow = window.open ("../blank.htm", "debugtrace",
		"menubar=no,status=no,width=440,height=350,scrollbars=no,toolbars=yes,resizable=no");
	
	debugwindow.document.write ('<html><body><p style="font: bold 10pt Arial;">LMS Session Trace</p>'
		+ '<p><form><textarea id="trace" style="font: 8pt Arial; width: 420px; height: 290px;">'
		+ debugtrace + '</textarea></form><p></body></html>');

	debugwindow.document.title = window.document.title + " LMS Session Trace";
	
	debugwindow.focus ();
}

function setcurrentpage ()
{
	var page = prompt ('Enter a path (ie: pages/splash.htm) to jump to that location:', '');

	if (page)
		parent.gotopage ('../../' + page);
}

// --------------------------------------- Error Handling

function reportError (message)
{
	reportdebug (message);
	
	alert (message);
	undefinedCallToHaltExecution ();
}

// --------------------------------------- Test

var UTILITIES_VERSION = 1.9;

// --------------------------------------- End Of File
