// Copyright (c) 1998-2004 Araxis Ltd. All rights reserved.

// This Javascript file handles the cookies functionality.

// gets the value of a cookie
function getCookie(sName)
{
	// cookies are separated by a semicolon followed by a space
	var aCookie = document.cookie.split("; ");
	
	for (var i=0; i < aCookie.length; i++)
	{
		// a name-value pair is separated by an equal sign
		var aCrumb = aCookie[i].split("=");
		if (sName == aCrumb[0])
			return unescape(aCrumb[1]);
	}
	
    // the cookie does not exist
    return "";
}


// Sets the value of cookie.
// Expiry date of cookie is one year from today's date.
function setCookie(sName, sValue)
{
	var dateExp = new Date();
   	dateExp.setFullYear(dateExp.getFullYear() + 1);
    document.cookie = sName + "=" + escape(sValue) + ";path=/;expires=" + dateExp.toGMTString(); 
}

// deletes a cookie
function deleteCookie(sCookie)
{
	// we don't want to create an expired cookie!
	if (getCookie(sCookie) != "") 
	{
		// delete cookie by setting its expiry to a past date
		document.cookie = sCookie + "=;path=/;expires=Fri, 31 Dec 1999 23:59:59 GMT;";
	}
}

// if cookies are enabled returns true, otherwise false
function areCookiesEnabled()
{
	setCookie("dxCookieTest", "dxEnabled");
	var fCookiesEnabled = (getCookie("dxCookieTest") == "dxEnabled");
	if (fCookiesEnabled)
		deleteCookie("dxCookieTest");
	return fCookiesEnabled;
}


//----
// Because of the limited number of cookies, we need to store lots of page-specific name/value pairs within a single cookie.
// Instances of this object make it easy to encode such pairs into a single string, which can then be stored in a cookie.
//
// The crumbs are stored in the cookie in a way that enables several sets of crumbs (one for each of several pages) 
// to be stored in a single cookie. The format of the cookie is:
//
//    [<pageName>:<pageCrumbs>][[+<pageName>:<pageCrumbs>]...]
//
// where <pageCrumbs> is the string representing the crumbs in this object. <pageCrumbs> is of the form:
//
//    [<crumbName>@<crumbValue>][[+<crumbName>@<crumbValue>]...]
//
// For example, <pageCrumbs> might be:
//
//    "id1@0+id2@1+id3@0"
//
// Crumb name and values must be of the form [a-zA-Z0-9]+.
//----

function Crumbs_toString()
{
	return this.sCrumbs;
}

// returns an array of strings in the form of <crumbName>@<crumbValue>, each representing a crumb name/value pair.
function Crumbs_toArray()
{
	return this.sCrumbs.split("+");
}

function Crumbs_setCrumb(sCrumbName, sCrumbValue)
{
	// keep track of which blocks have been actioned by the user
	var iIndex = this.sCrumbs.indexOf(sCrumbName);

	if (iIndex == -1)
	{
		// if this tab control hasn't been actioned yet
		if (this.sCrumbs.length != 0) 
		{
			this.sCrumbs += "+";
		}
		this.sCrumbs += sCrumbName + "@" + sCrumbValue;
	}
	else
	{
		// if we have already stored a state for this tab control, update it
		var re = new RegExp(sCrumbName + "@\\w", "g");
		this.sCrumbs = this.sCrumbs.replace(re, sCrumbName + "@" + sCrumbValue);
	}
}

function Crumbs_getCrumb(sCrumbName)
{
	var aCrumbValuePairs = this.sCrumbs.split("+");
	
	for (var i = 0; i < aCrumbValuePairs.length; i++)
    {
    	var aCrumbComponents = aCrumbValuePairs[i].split("@");
    	if (aCrumbComponents[0] == sCrumbName)
    	{
    		return aCrumbComponents[1];
    	}
	}
	
	return "";
}

// Stores the crumbs represented by this object in a cookie.
function Crumbs_storePageSpecificCrumbsInCookie()
{
	if (!areCookiesEnabled())
		return;

	// if there are no crumbs, don't do anything if there is no state to store for this page
	if (this.sCrumbs.length == 0)
		return;
	
	// If we are approaching the maximum cookie length of 4K, we need to ensure it is not exceeded,
	// otherwise the whole cookie will be deleted (at least on IE). Therefore the oldest persisted page state
	// is discarded in favour of the new one.
	var sCookie = getCookie(this.sCookieName);
	
	while (sCookie.length > 3800)
	{
		var iOldCookieLength = sCookie.length;
		sCookie = sCookie.substring(sCookie.indexOf("/",1));
		
		// recover gracefully something goes wrong, such as the first item in the cookie being more than 3800 characters
		if (iOldCookieLength == sCookie.length) // should never happen
			sCookie = "";
	}

	var i = 0;
	var fStoredCrumb = false;
	
	// not the most efficient way of doing this, but it's easy to understand
	var aCookieFragments = sCookie.split("/");	
		
	if (sCookie.length > 0)
	{
		for (; i < aCookieFragments.length; i++)
	    {
	        var aFragmentComponents = aCookieFragments[i].split(":");
	        if (aFragmentComponents[0] == this.sPageId)
	        {
	            aFragmentComponents[1] = this.sCrumbs;
	            aCookieFragments[i] = aFragmentComponents.join(":");
	            fStoredCrumb = true;
	            break;
	        }
		}
	}
	
	if (!fStoredCrumb) // this page doesn't yet have any cookies stored for it
	{
		aCookieFragments[i] = this.sPageId + ":" + this.sCrumbs;
	}
	
	setCookie(this.sCookieName, aCookieFragments.join("/"));
}

function Crumbs_loadPageSpecificCrumbsFromCookie()
{
	if (!areCookiesEnabled())
		return "";

	// not the most efficient way of doing this, but it's easy to understand
    var aCookieFragments = getCookie(this.sCookieName).split("/");
   
    for (var i = 0; i < aCookieFragments.length; i++)
    {
        var aFragmentComponents = aCookieFragments[i].split(":");
        if (aFragmentComponents[0] == this.sPageId)
        {
			return aFragmentComponents[1];
		}
	}
	return "";
}

function Crumbs_deletePageSpecificCrumbsFromCookie()
{
	if (!areCookiesEnabled())
		return;

	var sCookie = getCookie(this.sCookieName);
	var aCookieFragments = sCookie.split("/");
	var aCookieFragmentsNew = new Array();
	var iCookieNewIndex = 0;
	for (var i = 0; i < aCookieFragments.length; i++)
	{
		var aFragmentComponents = aCookieFragments[i].split(":");
		if (aFragmentComponents[0] != this.sPageId && aFragmentComponents.length == 2)
		{
			aCookieFragmentsNew[iCookieNewIndex++] = aCookieFragments[i];
		}
	}

	setCookie(this.sCookieName, aCookieFragmentsNew.join("/"));
	this.sCrumbs = "";
}

// Constructor for Crumbs objects.
//
// sPageId -- a string representing the page to which the crumbs belong. This should be unique for a given domain.
// sCookieName -- the name of the cookie in which the page's crumbs are to be stored
function CrumbsCtor(sPageId, sCookieName)
{
	// methods
	this.toString = Crumbs_toString;
	this.toArray = Crumbs_toArray;
	this.setCrumb = Crumbs_setCrumb;
	this.getCrumb = Crumbs_getCrumb;
	this.storePageSpecificCrumbsInCookie = Crumbs_storePageSpecificCrumbsInCookie;
	this.deletePageSpecificCrumbsFromCookie = Crumbs_deletePageSpecificCrumbsFromCookie;
	this.loadPageSpecificCrumbsFromCookie = Crumbs_loadPageSpecificCrumbsFromCookie;

	// variables
	this.sPageId = sPageId;
	this.sCookieName = sCookieName;
	this.sCrumbs = this.loadPageSpecificCrumbsFromCookie();
}
