MEGA = function(aNameSpace,aDomain,aPath,aSecure,aTrace) {
	// Initialize
	this.segmentationVal		= "";
	this.nameSpace	= aNameSpace;
	this.domain		= aDomain;
	this.path		= aPath;
	this.secure		= aSecure;
	this.MEGAObjects			= new Object();
}
MEGA.prototype =
{
	init: function (aKeys)
	{
		this.segmentationVal = this.getCookie(this.nameSpace);
		for (this.MEGAObjects.length = 0;
				this.MEGAObjects.length < aKeys.length;
				this.MEGAObjects.length++)
		{
			this._keyInit(this.MEGAObjects.length,
				aKeys[this.MEGAObjects.length].name,
				aKeys[this.MEGAObjects.length].type,
				aKeys[this.MEGAObjects.length].bitMapSize,
				aKeys[this.MEGAObjects.length].unconditional,
				aKeys[this.MEGAObjects.length].val);
		}
		//Save the changed value in cookie...
		//...perhaps establish it for the first time
		this._storeVars();
	},
	macroinit: function ()
	{
		//Object approach to initialize
		var myobj = [
			{name:'ctyp', type:'int', bitMapSize:0, unconditional:false,val:0},
			{name:'calc', type:'int', bitMapSize:0, unconditional:false,val:0},
			{name:'cbuser', type:'int', bitMapSize:0, unconditional:false,val:0}];
		this.init(myobj);
	},
	exit: function ()
	{
	},
	//
	// Conditionally sets a segmentation's key's value if:
	// - The key is a known name
	// - The key is of type int
	// - The key's new value is > old value (unless aForseSetVar is true)
	// - The key's new value is an integer
	//
	conditionalSetInt: function(aKey, aValue, aForceSetVar)
	{
		// Returns:
		// 0 for success
		// 1 for invalid key name
		// 2 for no action taken
		// 3 for invalid key type (you tried to set a string type key to an integer)
		// 4 for invalid value (non-integer)
		//
		//Get Object by Name
		var irtrn = 0; //Assume success
		if (isNaN(parseInt(aValue))) {
			irtrn = 4; //Can't set value to a non integer
		} else {
			var MEGAObject = this._getObjByName (aKey);
			if (MEGAObject) {
				// Is this key Integer type?
				if (MEGAObject.type == "int") {
					if (aForceSetVar || 
				    	MEGAObject.value == "undefined" ||
						parseInt(aValue) >= MEGAObject.value)
					{
						MEGAObject.value	= aValue; //Argument sets the new cookmie's calue
						this._storeVars();	//Save the changed value in cookie
					} else {
						irtrn = 2; //No action taken
					}
				} else {
					irtrn = 3; //Invalid key type - can't set the value of a non int key to an int
				}	
			} else {
				//Object not found
				irtrn = 1;
			}
		}
		return irtrn;
	},
	//
	// Function to store compound Key=Value pairs for segmentation values
	// 
	_storeVars: function ()
	{
		// iterate through all keys
		// Construct output key=value string
 		// Set cookie
       	var cookie = "";
		for (idx = 0; idx < this.MEGAObjects.length; idx++) {
			if(idx) {
				cookie += "&";
			}
			cookie += this.MEGAObjects[idx].name + ":";
			cookie += this.MEGAObjects[idx].value;
		}
		this.segmentationVal = cookie;
		// The save the cookie in the .domain.com area
		this.setCookie(this.nameSpace,cookie,360);
	},
	//
	// Get Segmentation value from namespace's cookie for the provided key
	// Returns:
	//	null = cookie not found
	//	actual cookie value returned on success
	//
	_getSegmentationValByKey: function(cName)
	{
		var pos = this.segmentationVal.indexOf(cName + ":");
		var value = "";
		if (pos != -1) {
        	var start = pos + cName.length + 1; // added pos
			var end	  = this.segmentationVal.indexOf('&',start);
			if (end == -1) {
				end	  = this.segmentationVal.indexOf(';',start);
				if (end == -1) {
					end = this.segmentationVal.length;
				}
			}
			value = this.segmentationVal.substring(start,end);
		}
		return value;
	},
	//
	// Display functions
	//
	_displayAll: function()
	{
		for (idx = 0; idx < this.MEGAObjects.length; idx++) {
			this._displayObj(this.MEGAObjects[idx]);
		}
	},
	_displayObj: function (aMegaObject)
	{
		if (aMegaObject != null) {
			buf	= " Name["	+ aMegaObject.name	+ "]"
				+ " Val["	+ aMegaObject.value	+ "]"
				+ " type["	+ aMegaObject.type	+ "]"
				+ " Uncond["	+ aMegaObject.unconditional	+ "]";
			document.write("_displayObj(): " + buf+"<BR>");
		} else {
			alert ("Null object");
		}
	},
	//
	// Internal Utility functions
	//
	// Initialize Segmentation key with value provided.
	// 
	_keyInit: function(aIdx,aName,aType,aBitMapSize,aUnconditional,aValue)
	{
		this.MEGAObjects[aIdx]					= new Object();
		this.MEGAObjects[aIdx].name				= aName;
		this.MEGAObjects[aIdx].type				= aType;
		this.MEGAObjects[aIdx].bitMapSize		= aBitMapSize;
		this.MEGAObjects[aIdx].unconditional	= aUnconditional;
		// Segmentation Key's value is conditionally set from cookie - if available
		var sValue		= this._getSegmentationValByKey(aName);
		//
		// Initialize Segmentation key's value:
		// - If unconditional
		// - If current key value is undefined
		// - If new value is greater than current value
		// - If current value is null
		//
		if (aUnconditional || sValue == "undefined" || parseInt(aValue) > parseInt(sValue) || sValue.length < 1) {
			this.MEGAObjects[aIdx].value	= aValue; //Argument sets the new segmentation key's value
		} else {
			this.MEGAObjects[aIdx].value	= sValue; //segmentation key's previous value is used
		}
	},
	//
	// Return the Object for the Segmentation's key (aName)
	//
	_getObjByName: function (aName)
	{
    	var rtrn = null;
    	for (idx = 0; idx < this.MEGAObjects.length; idx++) {
		if (aName == this.MEGAObjects[idx].name) {
			rtrn = this.MEGAObjects[idx];
			break;
        	}
    	}
    	return rtrn;
	},
	//
	// setCookie()
	// Args:
	//	cName: Name of cookie to set (should be namespace used to Google Analytics tracking cookie
	//	value: Value to set cookie to
	//	expiredays:	Days in which cookie will expire
	//	TODO:
	//	domain:		Domain in which cookie is set, should be .mimeo.com or .mimeo.co.uk
	//	namespace:	Should namespace be added, or is cName the name space
	//	
	//
	// Returns: N/A
	//
	setCookie: function(aCookieName,aValue,aExpireDays)
	{
		var exdate=new Date();
		exdate.setDate(exdate.getDate()+aExpireDays);
		cookie = aCookieName+ "=" +escape(aValue) +
			( (aExpireDays==null) ? "" : ";expires="+exdate.toGMTString()) +
			( ( this.path ) ? ";path=" + this.path : "" ) +
			( ( this.domain ) ? ";domain=" + this.domain : "" ) +
			( ( this.secure ) ? ";secure=" + this.secure : "" );

		document.cookie = cookie;
	},
	getCookie: function(aKey)
	{
		var cookie = unescape(document.cookie);
		var pos = cookie.indexOf(aKey+"=");
		var value = "";
		if (pos != -1) {
        		var start = pos + aKey.length + 1;
			var end	  = cookie.indexOf(";",start);
			if (end == -1) {
				end = cookie.length;
			}
			value= cookie.substring(start,end);
		}
		return value;
	},
//
//Unit Tests for MEGAConditionalSetInt
//
	UnitTestMEGASetConditionalSetInt: function()
	{
		// UNIT Tests for MEGAConditionalSetInt
		// Returns:
		// 0 for success
		// 1 for invalid key name
		// 2 for no action taken
		// 3 for invalid key type (you tried to set a string type key to an integer)
		// 4 for invalid value (non-integer)
		//Set to valid value
		irtrn = this.conditionalSetInt("ctyp", 2, false);
		if (irtrn == 0) {
			document.write("0 was 0 UNIT TEST PASS: Sucessfully set ctyp<BR>");
		} else {
			document.write("0 was " +irtrn + "UNIT TEST FAIL: Failed to set ctyp irtrn [" + irtrn + "] <BR>");
		}
	
		//Set to valid value - force override
		irtrn = this.conditionalSetInt("ctyp", 1, true);
		if (irtrn == 0) {
			document.write("0 was 0 UNIT TEST PASS: Sucessfully set force to lower value ctyp<BR>");
		} else {
			document.write("0 was " +irtrn + "UNIT TEST FAIL: Failed to force set ctyp irtrn [" + irtrn + "] <BR>");
		}
		//Set to invalid value
		irtrn = this.conditionalSetInt("ctypng", 1, false);
		if (irtrn == 1) {
			document.write("1 was 1 UNIT TEST PASS: Invaid key name rejected ctypng<BR>");
		} else {
			document.write("1 was " + irtrn + "UNIT TEST FAIL: irtrn was [" + irtrn + "] but should have been a 1.<br>");
		}
	
	
		//Set to No Action Taken
		irtrn = this.conditionalSetInt("ctyp", 0, false);
		document.write("UNIT TEST - set value < current value w/o conditional override<br>");
		if (irtrn == 2) {
			document.write("2 was 2 UNIT TEST PASS: No Action Taken :ctyp<BR>");
		} else {
			document.write("2 was " + irtrn
				+ "UNIT TEST FAIL: Action inapproproately taken ctyp irtrn [" + irtrn + "] <BR>");
		}
	
		var MEGAObject = this._getObjByName ("ctyp");
		MEGAObject.type = "str";
		irtrn = this.conditionalSetInt("ctyp", 1, false);
		if (irtrn == 3) {
			document.write("3 was 3 UNIT TEST PASS: Can't set a string to an int ctyp<BR>");
		} else {
			document.write("3 was " +irtrn
				+ "UNIT TEST FAIL: Inapproproately set a string to an int ctyp irtrn [" + irtrn + "] <BR>");
		}
		MEGAObject.type = "int";

		//Set to Invalid Int value
		//Note: If the value started with an number, it would be parsed from the string & used.
		irtrn = this.conditionalSetInt("ctyp", "Not an int 1", false);
		if (irtrn == 4) {
			document.write("4 was 4 UNIT TEST PASS: Tried to set a non-int to an int rejected ctyp<BR>");
		} else {
			document.write("4 was " + irtrn
				+ "UNIT TEST FAIL: Inapproproately set an int to a non-int value ctyp irtrn [" + irtrn + "] <BR>");
		}
		//Display all objects
		this._displayAll();
	}
}
