// -----------------------------------------
// KNOWLEDGE MAP COOKIE MANAGEMENT FUNCTIONS
// -----------------------------------------
// Copyright (c) 2004-2007 The Salamander Organization Ltd.  All Rights Reserved.
//
// THIS WORK IS SUBJECT TO U.K. AND INTERNATIONAL COPYRIGHT LAWS AND TREATIES.
//
// DISCLAIMER:
//
// The Salamander Organization Ltd. (hereto referred as "Salamander") makes no representations or warranties
// with respect to the contents or use of this code, and specifically disclaims any express or implied
// warranties of merchantability or fitness for any particular purpose.  Further, Salamander reserves the right
// to revise this publication and to make changes to its content, at any time, without obligation to notify any
// person or entity of such revisions or changes.
//
// Further, Salamander makes no representations or warranties with respect to any software, and specifically
// disclaims any express or implied warranties of merchantability or fitness for any particular purpose.  Salamander
// reserves the right to make changes to any and all parts of the software, at any time, without obligation to notify
// any person or entity of such changes.
//
// Inclusion of the above notice does not necessarily imply publication.

// ################################
// ### GENERAL COOKIE FUNCTIONS ###

// save data to a cookie - provide the variable name to save against and the raw data to save
// no size checks are performed on the data so be sure that it is appropriate
function SaveToCookie(varName, cookieData, expiry)  
{
	// gets the current date and time
	var date = new Date();
	
	var expiryDate = "";
	var expiryString = "";
	var cookieString = "";
	var cookiePath = "";
	
	switch (expiry)
	{
		case "delete" :
		
			// set the expiry date in the past for a cookie deletion
			expiryDate = "Thu, 1 Jan 1970 00:00:00 GMT";
		
			break;
			
		case "year" :
		
			// set the expiry date to a year in the future
			date.setYear(date.getYear() + 1);
			
			expiryDate = date.toGMTString();
			
			break;
			
		default :
		
			// no expiry date - i.e. session-only cookie
			break;	
	}
	
	if (expiryDate != "")
	{
		expiryString = "expires=" + expiryDate + ";";
	}
	
	cookiePath = GetPath();
	
	if (cookiePath != "")
	{
		cookieString = "path=" + cookiePath;
	}

	document.cookie = varName + "=" + escape(cookieData) + ";" + expiryString + cookieString;
}

// get data from a cookie - provide the variable name to read
function GetFromCookie(varName)
{
	var cookieData = "";

	if (document.cookie)
	{
		var cookieVals = document.cookie.split(";");
		
		for (var i = 0; i < cookieVals.length; i++)
		{
			var cookieContents = cookieVals[i].split("=");
			
			var cookieVariable = StripChars(cookieContents[0], "spaces");
			
			if (cookieVariable == varName)
			{
				cookieData = unescape(cookieContents[1]);
				break;  // got the data - don't need to process the for loop any more
			}
		}
	}
	
	return cookieData;
}

// clear the values on a cookie variable
function ClearCookie(varName)
{
	if (document.cookie)
	{
		SaveToCookie(varName, "", "delete");
	}
}

// get the current MooD appropriate base path (i.e. the path minus a ../ or ../../)
function GetPath()
{
	var basePath = "/";  // initialise return as slash

	var fullURIPath = location.pathname;
	
	// strip document from path
	var fullPath = fullURIPath.substring(0,fullURIPath.lastIndexOf('/'));
	
	// strip preceeding slash
	var beginFwdSlash = new RegExp("^/", "gi");
	fullPath = fullPath.replace(beginFwdSlash, "");
	
	var urlDepth = 0;
	
	// based on the MooD urlPath, how deep are we into the site?
	if (pageUrlPath == "../")
	{
		urlDepth = 1;
	}
	else if (pageUrlPath == "../../")
	{
		urlDepth = 2;
	}
	
	if (fullPath != "")
	{
		var pathParts = fullPath.split("/");
		var partsCount = pathParts.length;
		var modPartsCount = partsCount - urlDepth;
		
		// reassemble the path, minus the last couple of directories depending on the MooD urlPath
		for (var i = 0; i < modPartsCount; i++)
		{
			basePath += pathParts[i] + "/";
		}
	}
	
	return basePath;
}

function ShowCookieContents()
{
	var output = "";

	if (document.cookie)
	{
		output = "Cookie contains:\n\n";
	
		var cookieVals = document.cookie.split(";");
		
		for (var i = 0; i < cookieVals.length; i++)
		{
			output += unescape(cookieVals[i]) + "\n\n";
		}
	}
	
	alert(output);
}


// #####################################
// ### SHARED STATE MEMORY FUNCTIONS ###

var pageVarPrefix = "kmapPageMemory_";
var resourceMenuVarPrefix = "kmapResMenuMemory_";

var varSplit = "||";
var pairSplit = "~";

// delete all the contents of all the state cookies
// -- needs updating for each additional state register
function ClearStateCookies()
{
	if (document.cookie)
	{
		for (var i = 0; i < maxStoredResMenuStates; i++)
		{
			var resMenuVar = resourceMenuVarPrefix + i;
			ClearCookie(resMenuVar);
		}
		
		for (var j = 0; j < maxStoredPageStates; j++)
		{
			var pageVar = pageVarPrefix + j;
			ClearCookie(pageVar);
		}
	}
}

// find or create a suitable variable name for this page's cookie
function GetCookieVar(stateType, savingData)
{
	var pagePath = location.pathname;
	var cookieVar = "";
	var oldestCookieVar = "";
	var oldestCookieDate = new Date();
	
	var invalidState = false;
	var cookiePrefix = "";
	var maxStates = 0;
	
	stateType = stateType.toLowerCase();  // case protection

	// configure for the selected state type
	switch (stateType)
	{
		case "resourcemenu" :
		
			// resource menu state cookies
			cookiePrefix = resourceMenuVarPrefix;
			maxStates = maxStoredResMenuStates;
		
			break;

		case "pagesection" :
		
			// page section state cookies
			cookiePrefix = pageVarPrefix;
			maxStates = maxStoredPageStates;
		
			break;
		
		default :
			
			// invalid state type - error condition, though we're protected against this later
			invalidState = true;
			
			break;
	}

	if (document.cookie && !invalidState)
	{
		for (var i = 0; i < maxStates; i++)
		{
			var currentVar = cookiePrefix + i;
		
			var cookieData = new String(GetFromCookie(currentVar));
			
			if (cookieData != "")
			{
				// cookie has data, check to see if it is for this page
				var cookieParts = cookieData.split(varSplit);
				
				if (cookieParts.length >= 2)
				{
					// cookie data exists and has an expected number of parts to it
					
					if (cookieParts[0] == pagePath)
					{
						// this cookie is for this page
						cookieVar = currentVar;						
						break;  // found it, stop searching
					}
					else
					{
						// this cookie is for some other page
						
						// check to see if this is the oldest cookie in the history stack
						var currentCookieDate = new Date(cookieParts[1]);
						
						if ((currentCookieDate < oldestCookieDate) && savingData)
						{
							oldestCookieVar = currentVar;
							oldestCookieDate = currentCookieDate;
						}
					}
				}
				else
				{
					// cookie data exists, but doesn't conform to expectations
					if (savingData)
					{
						// must be old data, so overwrite
						cookieVar = currentVar;
						break;  // got a suitable one, stop searching
					}
				}
			}
			else
			{
				// cookie exists but has no data
				if (savingData)
				{
					// we can use this var name
					cookieVar = currentVar;
					break;  // got a suitable one, stop searching
				}
			}
		}
		
		if ((cookieVar == "") && savingData)
		{
			// all cookies were in use, we'll need to replace the oldest one then
			cookieVar = oldestCookieVar;
		}
	}
	
	return cookieVar;
}

// modify a set of cookie data based on a variable-value pair
// SUMMARY:
//		oldCookieData			- string of the previous cookie data (NOT the entire cookie though!)
//		pairVar					- string of the variable name to search the data for and/or set afresh
//		pairVal					- string of the value for pairVar
//
// CONCEPT:
// From a particular -cookie- var-value pair, get the value.  That value is the old cookie data.
// Then parse that old data looking for the state var-value pairs.
// If we find the old state variable, pull it out.
// Whether we find it or not, add the new state var-value at the end of the cookie data.
// Update the last modified details on these state var-values.
// Then return a new and updated cookie, containing everything the old cookie did, but updated with new details.
function ModifyCookieData(oldCookieData, pairVar, pairVal)
{
	var newCookieArray = new Array();
	var updatedCookie = false;
	
	var newCookieData = "";
		
	var newData = pairVar + pairSplit + pairVal;
	
	// add basic data onto new cookie
	newCookieArray[0] = location.pathname;
	newCookieArray[1] = new Date();
	
	if (oldCookieData != "")
	{
		// we need to modify the old cookie
		var cookieString = new String(oldCookieData);
		var cookieParts = cookieString.split(varSplit);
		
		// add page data again
		
		if (cookieParts.length > 2)
		{
			for (var i = 2; i < cookieParts.length; i++)
			{
				var pairString = new String(cookieParts[i]);
				var pairParts = pairString.split(pairSplit);

				if (pairParts.length == 2)
				{
					// got an expected pair, parse it and remove its data
					if (pairParts[0] == pairVar)
					{
						// variable names match - clear out the old data so we can add it to the end of the array
						newCookieArray[i] = "";
					}
					else
					{
						// leave the old data as is
						newCookieArray[i] = pairString;
					}
				}
				else
				{
					// must not be a var-value memory pair as expected - just write back verbatim
					// -- this could be an error condition
					newCookieArray[i] = pairString;
				}
			}
		}
		
		// assemble new data and add it to the end
		newCookieArray[cookieParts.length] = newData;

		updatedCookie = true;
	}
	else
	{
		// we need to build a new cookie
		newCookieArray[2] = newData;
		
		updatedCookie = true;
	}
	
	if (updatedCookie)
	{		
		var justAdded = false;
		
		// assemble the updated cookie into a string
		for (var j = 0; j < newCookieArray.length; j++)
		{
			// only add items to the output if they're not "blank"
			if (newCookieArray[j] != "")
			{
				if (!justAdded)
				{
					// first item
					newCookieData = newCookieArray[j];
				}
				else
				{
					// all other items
					newCookieData += varSplit + newCookieArray[j];
				}
				
				justAdded = true;
			}
		}
	}
	else
	{
		// cookie wasn't updated, so just give back the old cookie data
		newCookieData = oldCookieData;
	}
	
	return newCookieData;
}
