/**
 * @singleton MVTest
 */
MVTest = {};     

/**
 * name of the tracked variant name
 */
MVTest.varName = "eVar25";

/**
 * the QS parameter passed from the launcher with the user's test-name and group
 */
MVTest.launcherQSValue = "variation";

/**
 * The value for user groups for users that are yet to download a file
 */
MVTest.notAlocatedValue = "";

/**
 * URL of a server-side script that runs from oberon-media subdomain 
 * and returns an empty text-file as a script resource, 
 * allongside a server-side generated HTTP Set-Cookie headers from its domain.
 */
//MVTest.oberonCookieSetterURL = "http://catalog-prod.apizone.oberon-media.com/GroupTests/2000.0/SetGroup.aspx";

/**
 * days for expiry of user-group mark cookie
 * @type Number
 */
MVTest.cookieExpiryDate = null;

/**
 * The name of the test
 * @type String
 */
MVTest.testName = null;

/**
 * @type Array
 */
MVTest.groups = [];

/**
 * returns true if the singleton is initiated well 
 * @type bool
 */
MVTest.isWellInitiated = function()
{
	if (!this.log)
	{
		return  this.testName.length > 0 
			&&	this.groups.length > 0  
			&&	this.groups[0] 
			&&	this.UTCExpiry != "NaN" 
			&&	(new Date()).getTime() < (new Date(this.UTCExpiry)).getTime()
			;
	}	
	
	var isOK = true;
	if (!this.testName.length)
	{
		this.log.error("No test name provided.");
		isOK =  false;
	}

	if (this.groups.length == 0 || !this.groups[0])
	{
		this.log.error("No test groups provided.");
		isOK =  false;
	}

	if (this.UTCExpiry == "NaN")
	{
		this.log.error("Expiry string does not parse into a valid date.");
		isOK =  false;
	}

    if ( (new Date()).getTime() > (new Date(this.UTCExpiry)).getTime() )
    {
		this.log.debug("Expiry date has passed.");
        isOK =  false;
    }

	return isOK;
}

/**
 * Save user groupt to cookies
 *
 * @param {String} sGroupName - the user group name
 */
MVTest.persistUserGroup = function(sGroupName)
{
	/**
	 * Cookie domain - 
	 * cut the subdomain and leave "." as first char for the domain
	 * when no subdomain - use "www" as default
	 */
	var domain = location.host;
	//domain is like xxx.co.uk, xx.co.il, ect
	if(domain.charAt( domain.length - 6) == ".")
	{
		if( domain.indexOf(".", domain.indexOf(".", domain.indexOf(".")) + 1) == -1 ) domain = "www." + domain;

	//domain is like xxx.com, xxx.org, xxx.de
	}else{
		if( domain.indexOf(".", domain.indexOf(".") + 1) == -1 ) domain = "www." + domain;
	}
	domain = domain.substr(domain.indexOf("."));

    /**
     * Set the cookie
     */
	document.cookie = [ this.testName, '=', sGroupName
	                  , '; expires=' , this.UTCExpiry
	                  , '; domain=' , domain
	                  ].join("");
    Cookies.rawByName[this.testName] = sGroupName;

	/**
	 * Set the cookie in Oberon-Media
	 */
//	 this.markUserInOberonDomain();    
}

/**
 * returns if the current user is allocated to a test-group
 * @type String
 */
MVTest.isUserAllocated = function()
{
	return !!Cookies.rawByName[this.testName];
}

/**
 * when the page is reached from the launcher after the user cleared his cookies
 * we get a chance to rebound him to his original group.
 * This case is identified when the 
 */
MVTest.assureQSVariantBinding = function()
{
    var sQsVariation = Url.here.params[ this.launcherQSValue ];
    if (!sQsVariation || this.isUserAllocated()) return;

    sQsVariation = sQsVariation.split("-");
    if  (sQsVariation.length < 2 || sQsVariation[0] != this.testName) return;

    this.persistUserGroup(sQsVariation[1]);
}


/**
 * Initializes the Singleton with the first parameter as Test-Name, 
 * and the rest of the parameters as test-group names.
 *
 * @param {string} sTestName
 *      The name of the test, expected to be pulled from channel-property.
 *      Only alphanumeric chars left, while the rest are replaced by underscore "_".
 * @param {string} sExpiry
 *      String describing the expiration date of the test, expected to be pulled from channel-property
 * @param {string} sGroupsList
 *      Comma-delimited values list, of the variant groups in the test, expected to be pulled from channel-property.<br>
 *      All spaces are taken out of this list, and only alphanumeric chars and dots are left, while the rest are replaced by underscore "_".
 * @param {String(optional)} sOberonCookieSetterURL
 *      Updates {@link MVTest#oberonCookieSetterURL} during initiation.
 *      The default value is: http://catalog-prod.apizone.oberon-media.com/GroupTests/2000.0/SetGroup.aspx
 */
MVTest.init = function(sTestName, sExpiry, sGroupsList, sOberonCookieSetterURL)
{
	if (window.Log4Js && sTestName) this.log = new Log4Js.Logger("MVTest - " + this.sTestName );

	this.testName = String(sTestName).replace(/[^A-Z^a-z^0-9]/g, "_");
	this.UTCExpiry = new Date(sExpiry).toUTCString();
	this.groups = sGroupsList.replace(/\s/g, "").replace(/[^A-Z^a-z^0-9^\.^,]/g, "_").split(",");

//    if (sOberonCookieSetterURL && typeof(sOberonCookieSetterURL) == 'string') this.oberonCookieSetterURL = sOberonCookieSetterURL;
    
    if (!this.isWellInitiated()) return;

    /**
    * when the page is reached from the launcher after the user cleared his cookies
    * we get a chance to rebound him to his original group.
    * This case is identified when the 
    */    
    this.assureQSVariantBinding();
    
    /**
     * Takes over omnitureLogDownload and populates the tracked variable 
     */  
	this.takeOver();
}



/**
 * TRICKY:
 * =======
 * This function creates the same user-group cookie 
 *     on the OBERON-MEDIA domain
 * so it will be available for all appliactions under oberon-media 
 * (like checkout and user-account)
 *
 * This happens by creating an HTTP request to a resource under oberon-media
 * (which is also a script - but only to have it no influence on the UI)
 * THE IMPORTANT THING:
 * It is a hit to a resource from OBERON-MEDIA domain, 
 * that returns alongside the resource A SERVER SIDE Set-Cookie HTTP header.
 *
 */
MVTest.markUserInOberonDomain = function()
{
    var sMvUserGroup = Cookies.rawByName[this.testName];
    if (!sMvUserGroup) {
        if (this.log) this.log.warn("MVTest.markUserInOberonDomain() is called, but user is not allocated");
        return;
    }

    var sSetCookieURL = this.oberonCookieSetterURL;
    
    sSetCookieURL = Url.appendParamValue(sSetCookieURL, "refid"  , this.testName);
    sSetCookieURL = Url.appendParamValue(sSetCookieURL, "code"   , sMvUserGroup );
    sSetCookieURL = Url.appendParamValue(sSetCookieURL, "expires", this.UTCExpiry.replace("UTC","GMT"));

    var oScript = document.createElement('SCRIPT');
    oScript.src = sSetCookieURL;
    
    if (this.log) this.log.warn("MVTest.markUserInOberonDomain() is called. URL hit: [" + oScript.src + "]");

    document.body.appendChild(oScript); 
}
 

/**
 * selects a group for the user and writes it in a cookie
 * @private
 * @returns the user group name
 * @type String
 */
MVTest.allocateUserToGroup = function() 
{
	/**
	 * Assure consistancy with previous alloation, if any
	 */
	var sGroupName = Cookies.rawByName[this.testName]
	if( sGroupName ) return sGroupName;

	/**
	 * Create a random allocation
	 */
    var currentDateMillis = (new Date()).getTime(); 
    var sGroupIndex = currentDateMillis % this.groups.length; 
	
	sGroupName = this.groups[sGroupIndex];

	/**
	 * Set the cookie
	 */
	this.persistUserGroup(sGroupName);
	
	if (this.log) this.log.info("User is allocated to group [" + sGroupName + "]");

    return sGroupName;
}

/**
 * gets the user group, 
 * or returns "not-allocated" for users that are yet to be allocated
 * @returns the user group name
 * @type String
 */
MVTest.getUserGroup = function()
{
	var sGroupName = Cookies.rawByName[this.testName] || this.notAlocatedValue;

	if (this.log) this.log.info("User is allocated to group [" + sGroupName + "]");

    return sGroupName;
}

/**
 * Populates value into the tracking variant.
 * This implementation covers omniture Code-G and Code-H.
 *
 * @param {string} 
 */
MVTest.onPopulateTrackingVar = function(sMvUserGroup)
{
    /**
     * prepare tracked variant
     */
    var sTrackedValue = this.testName + "-" + sMvUserGroup;
    
    /**
     * populate code-G
     **/
    window["s_" + this.varName] = sTrackedValue;
    
    /**
     * populate code-H if present
     **/
    if(typeof(window.s) == 'object') s[this.varName] = sTrackedValue;
}

/**
 * wrap for logDownload to preserve 'this' scope and the 'event' object(FF/IE)
 *
 * TRICKY: executed from the A.onclick event scope, and not from MVTest scope!
 *
 * @param {Number} pCode 
 *           The product code of the original game
 * @param {String} omnitureChannel 
 *           The omniture suit of the channel
 * @param {String} gameReportName 
 *           The report-name of the original game
 * @private
 */
MVTest_omnitureLogDownload = function(gameCode, omnitureChannel, gameReportName)
{
	MVTest.omnitureLogDownload(gameCode, omnitureChannel, gameReportName);
}

/**
 * Makes sure the user is allocated to a group
 * populates the evar name 
 * provides him a downloadable by his group
 * and calls the original omniture implementation
 * 
 * @param {Number} pCode 
 *           The product code of the original game
 * @param {String} omnitureChannel 
 *           The omniture suit of the channel
 * @param {String} gameReportName 
 *           The report-name of the original game
 * @private
 */
MVTest.omnitureLogDownload = function(gameCode, omnitureChannel, gameReportName)
{
	if (this.log) this.log.info("download clicked for game [" + gameReportName + "]");

	var oDwnld = {code: gameCode, channel: omnitureChannel, reportName: gameReportName};

	var sMvUserGroup = this.allocateUserToGroup();
	if (sMvUserGroup)
	{
		/**
		 * Allocate the user
		 */
		if (this.log) this.log.debug("user group: [" + sMvUserGroup + "]");

		/**
		 * populate evar
		 */
		 this.onPopulateTrackingVar(sMvUserGroup);

		/**
		 * Manipulate the <A>.href
		 */
		var myEvent = window.event;
		//mozilla based - extract the 'event' argument of the onclick event
		if(!myEvent)
		{
			var f = MVTest_omnitureLogDownload.caller;
			if (f && f.arguments &&  f.arguments.length)
				 myEvent = f.arguments[0];
		}
		var a = Event.findElement(myEvent,"A");
		if( a.href.indexOf( this.getUserGroup() ) == -1 )
		    a.href = a.href.replace( /\/exe\//gi  , "/exe/" + sMvUserGroup + "/" );

	}else{
		if (this.log) this.log.warn("user is not allocated to any group");
	}

	/**
	 * Call original omniture implementation
	 */
	this._omnitureLogDownload(oDwnld.code, oDwnld.channel, oDwnld.reportName);
}

/**
 * takes over the omniture calls
 */
MVTest.takeOver = function()
{
    if (window.omnitureLogDownload == undefined) 
		return setTimeout('MVTest.takeOver();',20);

	/**
	 * populate evar 
	 */
	var sMvUserGroup = this.getUserGroup();
    this.onPopulateTrackingVar(sMvUserGroup);

    /**
     * take over omnitureLogDownload function
     */
	this._omnitureLogDownload = window.omnitureLogDownload;
	window.omnitureLogDownload = MVTest_omnitureLogDownload;
	
	if (this.log) this.log.info("take-over complete");
}