document.write('<style type="text/css">\nbody {visibility: hidden;}</style>');

function lpopro_vars() {
	this.pageUrl = document.URL;
	this.pageReferrer = document.referrer;
	this.isControlScript = true;
	this.responsePoints = false;
	this.variations = false;
	this.page = "";
	this.experimentId = null;
	this.timeout = null;
	this.onloadfunc;
	this.isMSIE = /*@cc_on!@*/false;

	// these variables should be overwritten by client on page running experiments
	this.experimentIds = null;
	this.websiteId = null;
	this.js_url = null; // could be set to default url
	this.cookieDomain = null;

	// auxiliary variable used to create div to sanitize body's innerHTML
	this.pageDiv = null;

	this.lpoid = 0;
	this.variationIds = new Array();

	this.matches = 0;
	this.message = "";

	this.replaceBody = false;

	this.replacementDone = false;

	// Optional HTML DOM element within which replacements should be done.
	// Assign if you don't need to replace the whole body and want to avoid
	// various weird problems.
	this.context = false;

	this.timeout = 3000;
}

var LPOPRO_VARS = new lpopro_vars();

if (typeof(lpopro_custom_timeout) != "undefined" && !isNaN(lpopro_custom_timeout)) {
	LPOPRO_VARS.timeout = lpopro_custom_timeout;
}

/**
 * LPOPRO WS url
 */
LPOPRO_VARS.js_url = "//api.hurra.com/lpopro/ws/";

/**
 * LPOPRO_CONTROL class
 *
 */
function LPOPRO_CONTROL() {}

/*
 * cache classes as static methods of LPOPRO_CONTROL:
 */

//main class of cache - contains collection of response points
//and collection of combinations, moreover has id of experiment
LPOPRO_CONTROL.experiment = function() {
	this.rps = [];
	this.vars = [];
}

//assignment class -> is extends by lpopro_variation and lpopro_responsePoint
LPOPRO_CONTROL.assignment = function(id, evalSeq, bdTxtCnd, cgiNmCnd, cgiValCnd,
		refUrlCnd, stpAftHit, urlCnd, srchTxt, rplTxt) {
	this.id = id;
	this.evalSeq = evalSeq;
	this.bdTxtCnd = bdTxtCnd;
	this.cgiNmCnd = cgiNmCnd;
	this.cgiValCnd = cgiValCnd;
	this.refUrlCnd = refUrlCnd;
	this.stpAftHit = stpAftHit;
	this.urlCnd = urlCnd;
	this.srchTxt = srchTxt;
	this.rplTxt = rplTxt;
}

//classes to represent variations and response points
LPOPRO_CONTROL.variation = function() {}
LPOPRO_CONTROL.responsePoint = function() {}


/*
 * LPOPRO_CONTROL class static methods:
 */

LPOPRO_CONTROL.errhdl = function() {
	if (!document.body) {
		setTimeout(LPOPRO_CONTROL.errhdl, 100);
		return;
	}
	document.body.style.visibility = 'visible';
	if(document.getElementById('lpopro_test_span') == null) {
		if (LPOPRO_VARS.onloadfunc && typeof LPOPRO_VARS.onloadfunc == 'function') {
			LPOPRO_VARS.onloadfunc();
		}
	} else {
		clearTimeout(LPOPRO_VARS.timeout);
	}

}

LPOPRO_CONTROL.addLoadEvent = function(func) {
	if (window.addEventListener) {

		window.addEventListener("load", func, false);
	} else if (window.attachEvent) {
		window.attachEvent('onload', func);
	} else {
		LPOPRO_VARS.onloadfunc = window.onload;
		window.onload = func;
	}
}

LPOPRO_CONTROL.loadScript = function(src) {
	var lpoproScript = document.createElement("script");
	lpoproScript.setAttribute('type',"text/javascript");
	lpoproScript.setAttribute('src',src);
	document.getElementsByTagName("head").item(0).appendChild(lpoproScript);
	return lpoproScript;
}

/*
 * checkBody(bodyCondition) - tries to match given regular
 * expression to page content.
 *
 * Parameters: bodyCondition - body condition (can be a regular expression).
 * Should be sent in _T_W_O_ parts (e.g. "sam" + "ple");
 */
LPOPRO_CONTROL.checkBody = function(bodyCondition) {
	var timestamp = (new Date()).getTime();
	var marker = "dc0164b2-1e9e-11de-" + timestamp;
	bodyCondition = LPOPRO_CONTROL.encodeSearchtext(bodyCondition);
	var lpopro_bodycondition = document.createElement('div');
	lpopro_bodycondition.id = 'lpopro_bodycondition' + marker;
	lpopro_bodycondition.innerHTML = bodyCondition + marker;

	bodyCondition = LPOPRO_CONTROL.sanitize(lpopro_bodycondition.innerHTML, marker);

	bodyCondition = bodyCondition.replace(/\(/gi, "\\(");
	bodyCondition = bodyCondition.replace(/\)/gi, "\\)");
	bodyCondition = bodyCondition.replace(/xxFxPAREG_xx/gi, ")");
	bodyCondition = bodyCondition.replace(/xxFxPAREGxx/gi, "(");

	// List fix for IE - must be called after escaping parentheses!!
	bodyCondition = bodyCondition.replace(/<\/li>/gmi, '(\\s*$&)?');
	bodyCondition = LPOPRO_CONTROL.decodeReqularExpression(bodyCondition);
	var pageBody = LPOPRO_VARS.page;
	var re = new RegExp(bodyCondition, "gmi");
	var match = false;
    while (match = re.test(pageBody)) {
        if (!LPOPRO_CONTROL.isInsideForbiddenBlock(pageBody.substr(0, re.lastIndex))) {
        	return match;
        } else {
        	continue;
        }
    	pageBody = pageBody.substr(re.lastIndex);
    	re = new RegExp(bodyCondition, "gmi");
    }
}

/*
 * checkReferrer(referrer) - tries to match given referrer value
 * to current page referrer
 *
 * Parameters: referrer - referrer (can be a regular expression)
 */
LPOPRO_CONTROL.checkReferrer = function(referrer) {
	if(!LPOPRO_VARS.isMSIE) {
		LPOPRO_VARS.pageReferrer = encodeURIComponent(LPOPRO_VARS.pageReferrer);
		LPOPRO_VARS.pageReferrer = LPOPRO_CONTROL.decodeReqularExpression(LPOPRO_VARS.pageReferrer);
		referrer = encodeURIComponent(referrer);
		referrer = LPOPRO_CONTROL.decodeReqularExpression(referrer);
	}
	var re = new RegExp(referrer);
	return re.test(LPOPRO_VARS.pageReferrer);
}


/*
 * checkUrl(url) - tries to match given url value to current
 * page url
 *
 * Parameters: url - url (can be a regular expression)
 */
LPOPRO_CONTROL.checkUrl = function(url) {
	if(!LPOPRO_VARS.isMSIE) {
    	    url = encodeURIComponent(url);
    	    url = LPOPRO_CONTROL.decodeReqularExpression(url);
    }
	var re = new RegExp(url);
	return re.test(LPOPRO_VARS.pageUrl);
}

/*
 * checkCGIParameter(CGIParameter, CGIValue) - tries to match
 * given parameter and value to current page url parameters
 *
 * Parameters: CGIParameter - name of parameter to check (cannot be a
 * regular expression) CGIValue - value of the parameter (can be a regular
 * expression).
 */
LPOPRO_CONTROL.checkCGIParameter = function(CGIParameter, CGIValue) {
	var match = false;

	if(!LPOPRO_VARS.isMSIE){
		CGIParameter = encodeURIComponent(CGIParameter);
		CGIParameter = LPOPRO_CONTROL.decodeReqularExpression(CGIParameter);
		CGIValue = encodeURIComponent(CGIValue);
		CGIValue = LPOPRO_CONTROL.decodeReqularExpression(CGIValue);
	}

	if (LPOPRO_VARS.pageUrl.indexOf("?") > -1) {
	    var strQueryString = LPOPRO_VARS.pageUrl.substr(LPOPRO_VARS.pageUrl.indexOf("?")+1);
	    var aQueryString = strQueryString.split("&");
		for (var i = 0; i < aQueryString.length; i++) {
		    if (aQueryString[i].indexOf("=") > -1) {
		        var CGIval = aQueryString[i].split("=");
	            var re1 = new RegExp(CGIParameter);
	            var re2 = new RegExp(CGIValue);
				if (re1.exec(CGIval[0]) && re2.exec(CGIval[1])) {
				    match = true;
			        }
				}
		    }
		}
	return match;
}

/*
 * Decode special signs used in regular expression that are encoded by
 * encodeURIComponent function.
 *
 * Parameters: regex - regular expression to decode
 */
LPOPRO_CONTROL.decodeReqularExpression = function(regex) {
	regex = ' ' + regex;
	regex = regex.replace(/%5C/g, '\\');
	regex = regex.replace(/([^\\])%7C/g, '$1|');
	regex = regex.replace(/%2B/g, '+');
	regex = regex.replace(/([^\\])%5B/g, '$1[');
	regex = regex.replace(/([^\\])%5D/g, '$1]');
	regex = regex.replace(/%3F/g, '?');
	regex = regex.replace(/([^\\])%5E/g, '$1^');
	regex = regex.replace(/%24/g, '$');
	regex = regex.replace(/([^\\])%7B/g, '$1{');
	regex = regex.replace(/([^\\])%7D/g, '$1}');
	regex = regex.replace(/%3D/g, '=');
	regex = regex.replace(/%3A/g, ':');
	regex = regex.replace(/%25/g, '%');
	regex = regex.replace(/%26/g, '&');
	regex = regex.replace(/%2F/g, '/');
	regex = regex.replace(/%2C/g, ',');
	regex = regex.replace(/%3B/g, ';');
	regex = regex.replace(/%23/g, '#');
	regex = regex.substring(1);
	return regex;
}

/*
 * matchVariation(search, replacement) - tries to match given regular
 * expression to page content.
 *
 * Parameters: search, replacement - regexp values containing search and
 * replacement string respectively.
 */
LPOPRO_CONTROL.markVariation = function(prefix, suffix, variationId,varMatches, variationType) {
	var search = prefix + '((.|\\s)*?)' + suffix;
	// before this method countMatches should be run
	var matches = LPOPRO_CONTROL.countMatches(search);
	var replacement = '$1';
	var match = false;
	// Fetch site body from global variable.
	var pageBody = LPOPRO_VARS.page;
	// Reset variation matches counter (it is global variable).
	if (pageBody) {
		var localRe = new RegExp(search, "mi");
		var matched = null;
		var tmpBody = "";
		for (i=0;i<matches;i++) {
			var re = new RegExp(search,"gmi");
			matched = re.exec(pageBody);
			if (matched==null) return false;
			if (LPOPRO_CONTROL.isInsideForbiddenBlock(pageBody.substr(0, matched.index))) {
				continue;
			}
			match = true;
			var leftSide = pageBody.substr(0, matched.index);
			var rightSide = pageBody.substr(re.lastIndex, pageBody.length - re.lastIndex);
			var text = pageBody.substr(matched.index, re.lastIndex - matched.index);
			var replacementText = replacement;
			var openIndex = leftSide.lastIndexOf("<");
			var selfCloseIndex = leftSide.lastIndexOf("/>");
			var closeIndex = leftSide.lastIndexOf(">");
			var selfRightCloseIndex = rightSide.indexOf("/>");
			var rightCloseIndex = rightSide.indexOf(">");
			var idRegex = /\sid=/gi;
			var leftIdMatch = leftSide.toLowerCase().match(idRegex);
			if (leftIdMatch) {
				var leftIdPosition = leftSide.toLowerCase().lastIndexOf(leftIdMatch[leftIdMatch.length-1])+1;
			}
			else
				var leftIdPosition = -1;
			var leftIdMatched = /id=(?:"|'|)(\w+)(?:"|'|)/i.exec(leftSide.substr(leftIdPosition, leftSide.length - leftIdPosition));
					var rightIdMatch = rightSide.toLowerCase().match(idRegex);
			if (rightIdMatch) {
				var rightIdPosition = rightSide.toLowerCase().indexOf(rightIdMatch[0])+1;
			}
			else
				var rightIdPosition = -1;
			var rightIdMatched = /id=(?:"|'|)(\w+)(?:"|'|)/i.exec(rightSide.substr(rightIdPosition, rightSide.length - rightIdPosition));

			if (variationType == "V") {
					// Search text is not a part of any tag and does not contain any.
					if ( (openIndex < closeIndex) && (text.indexOf("<") == -1) && (text.indexOf(">") == -1) ) {
						LPOPRO_CONTROL.putVariationId(variationId,"lpo_variation_");
						var decoratorOpenTag = "<span class=\"lpopro_preview\" id=\"lpo_variation_" + LPOPRO_VARS.lpoid + "\">";
						var decoratorCloseTag = "</span>";
						replacementText = decoratorOpenTag + replacement + decoratorCloseTag;
					}
			// Search text is the entire opening tag, but without the content and closing tag
			// only search for id within search text
			// if id not found within the search text, create one
					else if (text.indexOf("<")>=0 && text.indexOf(">") == -1) {
						var idInText = text.match(/\\sid=(?:"|'|)(\w+)(?:"|'|)/i);
						if (idInText == null) {
							LPOPRO_CONTROL.putVariationId(variationId,"lpo_variation_");
							text = text.replace('>', ' id="lpo_variation_' + LPOPRO_VARS.lpoid + '">');
						}
					}
			// Search text is part of a tag.
			// Try to find id of a tag within left context (from begin of processed body to current match).
					else if (leftIdMatched && (leftIdMatched.index + leftIdPosition > openIndex)) {
						foundId = leftIdMatched[1];
						LPOPRO_CONTROL.putVariationId(variationId,foundId);
					}
			// If not found try to find id within right context (from current match to end of processed body).
			// Search text does not contain closing tag within itself.
					else if (text.indexOf(">") == -1 && rightIdMatched && (rightIdMatched.index + rightIdPosition < rightCloseIndex)) {
						foundId = rightIdMatched[1];
						LPOPRO_CONTROL.putVariationId(variationId,foundId);
					}
			// If id not found try to assign new one.
					else if (text.indexOf(">") == -1){
						LPOPRO_CONTROL.putVariationId(variationId,"lpo_variation_");
						rightSide = rightSide.replace(/(>|\/>)/," id=\"lpo_variation_"+ LPOPRO_VARS.lpoid +"\" $1");
					}
			// Search text contains some tag or group of tags. Wrap it with a span.
			// And add flag for highlighter indicating that a parent element should
			// be marked up (We can not highlight that span because we do not know
			// if there are block or inline tags within a search text.
			// Block tags inside span could break layout).
					else {
						LPOPRO_CONTROL.putVariationId(variationId,"lpo_get_parent");
						var decoratorOpenTag = "<span class=\"lpopro_preview\" id=\"lpo_get_parent" + LPOPRO_VARS.lpoid + "\">";
						var decoratorCloseTag = "</span>";
						replacementText = decoratorOpenTag + replacement + decoratorCloseTag;
					}
			}
			text = text.replace(localRe, replacementText);
			// page body is in fact remaining part of body
			pageBody = rightSide;
			tmpBody = tmpBody + leftSide + text;
		}
		LPOPRO_VARS.page = tmpBody + pageBody;
	}
	return match;
}

LPOPRO_CONTROL.putVariationId = function(variationId,lpoHtmlId) {
    var htmlId = null;
    if (lpoHtmlId.indexOf("lpo_")!=-1) {
    	LPOPRO_VARS.lpoid += 1;
        htmlId = lpoHtmlId + LPOPRO_VARS.lpoid;
    } else {
        htmlId = lpoHtmlId;
    }
    if (variationId) {
    	LPOPRO_VARS.variationIds[htmlId] = variationId;
    } else {
    	LPOPRO_VARS.variationIds[htmlId] = "factor_"+LPOPRO_VARS.lpoid;
    }
}

/*
 * matchVariation(search, replacement) - tries to match given regular
 * expression to page content.
 *
 * Parameters: search, replacement - regexp values containing search and
 * replacement string respectively.
 */
LPOPRO_CONTROL.matchVariation = function(search, replacement) {
	search = LPOPRO_CONTROL.decodeReqularExpression(search);

	var match = false;
	var pageBody = LPOPRO_VARS.page;

	if (replacement) {
		if (pageBody) {
			var re = new RegExp(search, "gmi");
			if (re.test(pageBody)) {
				LPOPRO_VARS.replaceBody = true;
				match = true;
				pageBody = pageBody.replace(re, replacement);
				LPOPRO_VARS.page = pageBody;
			}
		}
	}

	return match;
};

/*
 * matchOriginalVariation(search) - tries to match given regular
 * expression to page content.
 *
 * Parameters: search - regexp values containing search string
 */
LPOPRO_CONTROL.matchOriginalVariation = function(search) {
	search = LPOPRO_CONTROL.decodeReqularExpression(search);
	var match = false;
	var pageBody = LPOPRO_VARS.page;
	if (pageBody) {
		var re = new RegExp(search, "gmi");
	    while (match = re.test(pageBody)) {
	        if (!LPOPRO_CONTROL.isInsideForbiddenBlock(pageBody.substr(0, re.lastIndex))) {
	        	return match;
	        } else {
	        	continue;
	        }
	    	pageBody = pageBody.substr(re.lastIndex);
	    	re = new RegExp(search, "gmi");
	    }
	}
	return match;
};

/*
 * Replaces all occurences of a fixed string in a given text
 */
LPOPRO_CONTROL.replaceAll = function(strText, strTarget, strSubString) {
	var intIndexOfMatch = strText.indexOf( strTarget );
	while (intIndexOfMatch != -1){
		strText = strText.replace( strTarget, strSubString )
 		intIndexOfMatch = strText.indexOf( strTarget );
	}
	return strText ;
}


/*
 * Clears all incorrect entries in search text from div
 */
LPOPRO_CONTROL.sanitize = function(divText, marker) {
	var lastMarker = divText.indexOf(marker);
    divText = divText.substring(0, lastMarker);

	//re-replace brackets
	divText = LPOPRO_CONTROL.replaceAll(divText, 'xxFxQREGxx', '\?');
	divText = LPOPRO_CONTROL.replaceAll(divText, 'xxfxqregxx', '\?');
	divText = LPOPRO_CONTROL.replaceAll(divText, '%28', '(');
	divText = LPOPRO_CONTROL.replaceAll(divText, '%29', ')');
	divText = LPOPRO_CONTROL.replaceAll(divText, '&lt;', '<');
	divText = LPOPRO_CONTROL.replaceAll(divText, '&gt;', '>');
	divText = LPOPRO_CONTROL.replaceAll(divText, 'xxFxBSLHxx', "\\");
	divText = LPOPRO_CONTROL.replaceAll(divText, 'xxfxbslhxx', "\\");

	divText = divText.replace(/\s+/gm, '\\s*');
	return divText;
};

LPOPRO_CONTROL.appendResponsePointId = function(responsePointId) {
	if(LPOPRO_VARS.responsePoints) {
		LPOPRO_VARS.responsePoints += ',' + responsePointId;
	} else	{
		LPOPRO_VARS.responsePoints = 'rps=' + responsePointId;
	}
}

LPOPRO_CONTROL.appendVariationId = function(variationId) {
	if(LPOPRO_VARS.variations) {
		LPOPRO_VARS.variations += ',' + variationId;
	} else	{
		LPOPRO_VARS.variations = 'fvs=' + variationId;
	}
}

LPOPRO_CONTROL.createCookie = function(name,value,days) {
	if (days) {
		var date = new Date();
		date.setTime(date.getTime()+(days*24*60*60*1000));
		var expires = "; expires="+date.toGMTString();
	}
	else var expires = "";
	var cookieDomain = '';
	if (LPOPRO_VARS.cookieDomain != null) {
		cookieDomain = ' domain=' + LPOPRO_VARS.cookieDomain;
	}
	document.cookie = name+"="+value+expires+"; path=/;" + cookieDomain;
}

LPOPRO_CONTROL.deleteCookie = function(name) {
	document.cookie = name +'=; expires=0;';
}

LPOPRO_CONTROL.readCookie = function(name) {
	var nameEQ = name + "=";
	var ca = document.cookie.split(';');
	for(var i=0;i < ca.length;i++) {
		var c = ca[i];
		while (c.charAt(0)==' ') c = c.substring(1,c.length);
		if (c.indexOf(nameEQ) == 0) {
			var value = c.substring(nameEQ.length,c.length);
			if (value=='') return null;
			else if (value=='null') return null;
			else return value;
			}
		}
	return null;
}

LPOPRO_CONTROL.isCookie = function(name) {
	var nameEQ = name + "=";
	var ca = document.cookie.split(';');
	for(var i=0;i < ca.length;i++) {
		var c = ca[i];
		while (c.charAt(0)==' ') c = c.substring(1,c.length);
		if (c.indexOf(nameEQ) == 0) {
			return true;
			}
		}
	return false;
}

LPOPRO_CONTROL.compareEval = function(a, b) {
	var evalDiff = a.evalSeq - b.evalSeq;

	if (evalDiff != 0) return evalDiff;

	if (a.stpAftHit && !b.stpAftHit) {
		return 1;
	} else if (!a.stpAftHit && b.stpAftHit) {
		return -1;
	} else {
		return a.id - b.id;
	}
}

LPOPRO_CONTROL.getExperiment = function() {
	if (LPOPRO_VARS.experimentId == null) {
		LPOPRO_CONTROL.postProcessing();
		return false;
	}
	var src = LPOPRO_VARS.js_url + "lpopro-experiment.js?experiment_id=" + LPOPRO_VARS.experimentId + "&encoding=" + LPOPRO_CONTROL.getCharacterEncoding();
	var lpopro_assignments = LPOPRO_CONTROL.loadScript(src);

	if (LPOPRO_VARS.isMSIE) {
		lpopro_assignments.onreadystatechange = function () {
				   if (lpopro_assignments.readyState == 'loaded' || lpopro_assignments.readyState == 'complete') {
						   LPOPRO_CONTROL.runProcessing();
				   }
			}
	} else {
		   lpopro_assignments.onload=function() {
				LPOPRO_CONTROL.runProcessing();
		   }
	}

}


LPOPRO_CONTROL.encodeCommon = function(text) {
	return text;
}

LPOPRO_CONTROL.encodeText = function(text) {
	text = LPOPRO_CONTROL.encodeCommon(text);
	text = text.replace(/\?/gi, "xxFxQMARKxx");
	return text;
}

LPOPRO_CONTROL.encodeSearchtext = function(searchtext) {
	searchtext = LPOPRO_CONTROL.encodeCommon(searchtext);

	searchtext = searchtext.replace(/\\\)/gi, "_-TEMP-_");
	searchtext = searchtext.replace(/\)/gi, "xxFxPAREG_xx");
	searchtext = searchtext.replace(/_-TEMP-_/gi, ")");

	searchtext = searchtext.replace(/\\\(/gi, "_-TEMP-_");
	searchtext = searchtext.replace(/\(/gi, "xxFxPAREGxx");
	searchtext = searchtext.replace(/_-TEMP-_/gi, "(");

	searchtext = searchtext.replace(/\\\?/gi, "xxFxQMARKxx");
	searchtext = searchtext.replace(/\?/gi, "xxFxQREGxx");
	// x instead of # because IE puts / before first # in url
    searchtext = searchtext.replace(/\\/gi, "xxFxBSLHxx");
	return searchtext;
}

LPOPRO_CONTROL.decodeText = function(text) {
	text = text.replace(/xxFxQMARKxx/gi, "?");
	text = text.replace(/xxfxqmarkxx/gi, "?");
	return text;
}

/*
 * Makes the browser process the source given by setting it as innerHTML
 * in a fake DOM element innerHTML. Ensures that all src attributes are
 * cleared in order to avoid unwanted image requests. After pulling the
 * source back from the innerHTML, src attributes are re-attached.
 */
LPOPRO_CONTROL.innerhtmlize = function(source) {
	var origUrlRegexp = new RegExp('src="(.*?)"', 'gm');
	var lpopro_search = document.createElement('div');
	var origSrcs = new Array(); // the original src attributes from search text
	var origPaths = new Array(); // like origSrcs, but only the value of src
	var origPaths2 = new Array(); // like origPaths, but without xxFxBSLHxx

	var timestamp = (new Date()).getTime();
	var marker = "dc0164b2-1e9e-11de-" + timestamp;

	processed = source;

	var i = 0;
	while ((result = origUrlRegexp.exec(processed)) != null) {
		var orig = result[0];
		var orig2 = orig.replace(/xxFxBSLHxx/gm, '');
		origPaths[i] = result[1];
		origPaths2[i] = result[1].replace(/xxFxBSLHxx/gm, '');

		processed = processed.replace(orig, orig2);
		origSrcs[i] = orig;
		i++;
	}

	lpopro_search.innerHTML = processed + marker;
	processed = LPOPRO_CONTROL.sanitize(lpopro_search.innerHTML, marker);
	// change srcs back
	for (i = 0; i < origSrcs.length; i++) {
		var changeBackRegex = new RegExp('(src=".*?)' + origPaths2[i] + '(")', 'gmi');
		processed = processed.replace(changeBackRegex, '$1' + origPaths[i] + '$2');
	}

	return processed;
}

LPOPRO_CONTROL.prepareSearchText = function(searchText, assignment_id) {
	searchText = searchText.replace(/(href=["']?)xxFxBSLHxx\.xxFxBSLHxx\.\//gmi, '$1../');
	searchText = searchText.replace(/(href=["']?)xxFxBSLHxx\.\//gmi, '$1./');

	searchText = LPOPRO_CONTROL.innerhtmlize(searchText);

	searchText = searchText.replace(/\/(['" >])/gi, '/?$1');

	searchText = searchText.replace(/\(/gi, "\\(");
	searchText = searchText.replace(/\)/gi, "\\)");
	searchText = searchText.replace(/xxFxPAREG_xx/gi, ")");
	searchText = searchText.replace(/xxFxPAREGxx/gi, "(");
	searchText = searchText.replace(/xxFxBSLHxx/gi, "\\");

	// List fix for IE - must be called after escaping parentheses!!
	searchText = searchText.replace(/<\/li>/gmi, '(\\s*$&)?');

	return searchText;
}

LPOPRO_CONTROL.checkAssignmentsCondition = function(assignment, assignment_condition) {
	if (assignment.bdTxtCnd){
		if (assignment_condition) assignment_condition = LPOPRO_CONTROL.checkBody(assignment.bdTxtCnd);
	}
	if (assignment.refUrlCnd){
		if (assignment_condition) assignment_condition = LPOPRO_CONTROL.checkReferrer(assignment.refUrlCnd);
	}
	if (assignment.cgiNmCnd && assignment.cgiValCnd){
		if (assignment_condition) assignment_condition = LPOPRO_CONTROL.checkCGIParameter(assignment.cgiNmCnd, assignment.cgiValCnd);
	}
	if (assignment.urlCnd){
		if (assignment_condition) assignment_condition = LPOPRO_CONTROL.checkUrl(assignment.urlCnd);
	}

	return assignment_condition;
}

/*
 * Performs some tests in order to ensure that currently matched
 * regular expression pattern resides inside valid context.
 * Returns true when matched pattern resides inside forbidden context,
 * otherwise returns false.
 *
 * Invalid contexts:
 * 1) commented block  - e.g. &lt;!-- pattern --&gt;
 * 2) script block - e.g. &lt;script language="javascript"&gt;pattern&lt;/script&gt;
 * 3) inline script block - e.g. &lt;script language="javascript" src="pattern" /&gt;
 *
 * @param String leftContext - string laying left to the matched pattern,
 * @return boolean - true when matched pattern resides inside forbidden
 *                   context, false otherwise.
 */
LPOPRO_CONTROL.isInsideForbiddenBlock = function(leftContext)
{
  var commentRe = new RegExp("<!--(?!(.|\n)*-->)", "gm");
  var scriptRe = new RegExp("<script(?!(.|\n)+<\/script>)", "gmi");
  var inlineScriptRe = new RegExp("<script.*/>", "gmi");

  if (leftContext.search(commentRe) != -1) {
    return true;
  }
  var matched = null;
  while((matched = scriptRe.exec(leftContext)) != null) {
    var inlineContext = leftContext.substr(matched.index, leftContext.length);

    if (inlineContext.search(inlineScriptRe) != -1) {
      continue;
    }
    return true;
  }
  return false;
}

LPOPRO_CONTROL.countMatches = function(search, id) {
	var count = 0;
	var pageBody = LPOPRO_VARS.page;
	var srchText = LPOPRO_CONTROL.encodeSearchtext(search);

	srchText = LPOPRO_CONTROL.prepareSearchText(srchText, id);
	srchText = LPOPRO_CONTROL.decodeReqularExpression(srchText);

	// reset variation matches counter (it is global variable)
	if (srchText) {
		if (pageBody) {
			var re = new RegExp(srchText, "gmi");
            while (re.test(pageBody)) {
                if (!LPOPRO_CONTROL.isInsideForbiddenBlock(pageBody.substr(0, re.lastIndex))) {
                	count += 1;
                } else {
                	continue;
                }
            	pageBody = pageBody.substr(re.lastIndex);
    			re = new RegExp(srchText, "gmi");
            }
		}
	}
	return count;
}

LPOPRO_CONTROL.match = function(id,searchText, rplTxt, assignment_condition) {

	var srchText = LPOPRO_CONTROL.encodeSearchtext(searchText);

	srchText = LPOPRO_CONTROL.prepareSearchText(srchText, id);

	if (rplTxt == null) {
		if(assignment_condition) assignment_condition = LPOPRO_CONTROL.matchOriginalVariation(srchText);
	} else {
		if(assignment_condition) assignment_condition = LPOPRO_CONTROL.matchVariation(srchText , rplTxt);
	}

	return assignment_condition;
}

LPOPRO_CONTROL.cookieMonster = function() {
	var lpopro_combinationId_cookie = LPOPRO_CONTROL.readCookie('__lpopro_combinationid');

	if (lpopro_combinationId_cookie == null && LPOPRO_VARS.experimentId != null) {
		LPOPRO_CONTROL.createCookie('__lpopro_combinationid', LPOPRO_VARS.experimentId, 365);
	}

}

LPOPRO_CONTROL.preparePageContent = function() {
	LPOPRO_VARS.page = LPOPRO_VARS.page.replace(/\r/gm, ' ');
	LPOPRO_VARS.page = LPOPRO_VARS.page.replace(/\n/gm, ' ');
	LPOPRO_VARS.page = LPOPRO_VARS.page.replace(/\t/gm, ' ');
	LPOPRO_VARS.page = LPOPRO_CONTROL.encodeText(LPOPRO_VARS.page);
}

LPOPRO_CONTROL.runProcessing = function() {
	LPOPRO_CONTROL.cookieMonster();
	LPOPRO_CONTROL.preparePageContent();
    var rps = LPOPRO_VARS.experiment.rps;
	var vars = LPOPRO_VARS.experiment.vars;
	var assignments = rps.concat(vars).sort(LPOPRO_CONTROL.compareEval);
	if(!assignments) return false;

	var continue_process = true;
	for (var i=0;i<assignments.length;i++){
		var assignment_condition = true;

		if (!continue_process) continue;

		assignment_condition = LPOPRO_CONTROL.checkAssignmentsCondition(assignments[i], assignment_condition);

		// if search text is not null it means that assignment is variation
		if (assignments[i].srchTxt != null) {

			assignment_condition = LPOPRO_CONTROL.match(assignments[i].id, assignments[i].srchTxt, assignments[i].rplTxt, assignment_condition);

			if(assignment_condition) LPOPRO_CONTROL.appendVariationId(assignments[i].id);
		}

		if (!assignments[i].srchTxt) {
			if (assignment_condition) LPOPRO_CONTROL.appendResponsePointId(assignments[i].id);
		}

		if (assignments[i].stpAftHit) {
			if(assignment_condition) continue_process = false;
		}
	}

	// setTimeout is necessary here, do not remove if you are not sure what you are doing!
    setTimeout('LPOPRO_CONTROL.postProcessing();', 0);
	LPOPRO_CONTROL.track();

	return true;
}

LPOPRO_CONTROL.postProcessing = function() {
	document.body.style.visibility = 'visible';

	if (LPOPRO_VARS.onloadfunc) {
		LPOPRO_VARS.onloadfunc();
		LPOPRO_VARS.onloadfunc = null;
	}

	if (LPOPRO_CONTROL.postprocessingCallback && LPOPRO_VARS.replaceBody) {
		LPOPRO_CONTROL.callPostprocessingCallback();
	}
}

LPOPRO_CONTROL.replaceBody = function() {
	if (LPOPRO_VARS.replaceBody) {
		if (LPOPRO_VARS.context) {
			LPOPRO_VARS.context.innerHTML = LPOPRO_CONTROL.decodeText(LPOPRO_VARS.page);
		} else {
			document.body.innerHTML = LPOPRO_CONTROL.decodeText(LPOPRO_VARS.page);
		}
	}
	LPOPRO_VARS.replacementDone = true;
}

LPOPRO_CONTROL.track = function() {
	LPOPRO_CONTROL.replaceBody();

	var src = LPOPRO_VARS.js_url + 'lpopro-tracking.js?';
	var timestamp = (new Date()).getTime();

	src+='experiment_id=' + LPOPRO_VARS.experimentId + '&rnd=' + timestamp;
	if (LPOPRO_VARS.responsePoints)
		src+='&' + LPOPRO_VARS.responsePoints;
	if (LPOPRO_VARS.variations)
		src+='&' + LPOPRO_VARS.variations;
	LPOPRO_CONTROL.loadScript(src);

}

LPOPRO_CONTROL.waitForSession = function() {
	LPOPRO_CONTROL.pageDivFilter();
	var url = LPOPRO_VARS.pageUrl;
	var experimentIds = null;
	if (LPOPRO_VARS.experimentIds != "undefined") {
		experimentIds = LPOPRO_VARS.experimentIds;
	}
	var websiteId = null;
	var src = "";
	if (LPOPRO_VARS.websiteId != "undefined")
		websiteId = LPOPRO_VARS.websiteId;

	if (experimentIds != null) {
		src = LPOPRO_VARS.js_url + "lpopro-visit.js?campaign_ids=" + experimentIds + "&url="+encodeURIComponent(url);
	}
	if (websiteId != null) {
		src = LPOPRO_VARS.js_url + "lpopro-visit.js?website_id=" + websiteId + "&url="+encodeURIComponent(url);
	}
	if (LPOPRO_CONTROL.readCookie('__lpopro_combinationid')!=null) {
		src+= "&experiment_id="+LPOPRO_CONTROL.readCookie('__lpopro_combinationid');
	}
	if (src!="") {
		var lpopro_session = LPOPRO_CONTROL.loadScript(src);
		if (LPOPRO_VARS.isMSIE) {
			lpopro_session.onreadystatechange = function () {
				if (lpopro_session.readyState == 'loaded' || lpopro_session.readyState == 'complete') {
					LPOPRO_CONTROL.getExperiment();
				}
			}
		} else {
			lpopro_session.onload=function() {
				LPOPRO_CONTROL.getExperiment();
			}
		}
	} else {
    	LPOPRO_CONTROL.postProcessing();
	}
}

LPOPRO_CONTROL.getCharacterEncoding = function() {
	var charSet = "";
	// list of properties to try read for the current pages encoding.
	// document.characterSet is used by FF 2/3 &amp; Safari
	// document.charset is used by IE 6/7
	// the others are for belt and braces
	var testList = ["document.characterSet",
		"document.charset",
		"document.defaultCharset",
		"document.actualEncoding",
		"document.inputEncoding"
	];
	for (var i=0;i<testList.length;i++) {
		try {
			charSet="notset";
			eval("charSet = "+testList[i]+";");
			if (charSet != "" && charSet != null) {
				break;
			}
		} catch(e) {
		}
	}

	return charSet;
}

LPOPRO_CONTROL.pageDivFilter = function() {
	LPOPRO_VARS.pageDiv = document.createElement('div');
	LPOPRO_VARS.pageDiv.id = 'lpopro_pageDiv';
	LPOPRO_VARS.pageDiv.setAttribute('style','visibility:hidden');
	if (LPOPRO_VARS.context) {
		LPOPRO_VARS.pageDiv.innerHTML = LPOPRO_VARS.context.innerHTML;
	} else {
		LPOPRO_VARS.pageDiv.innerHTML = document.body.innerHTML;
	}
	LPOPRO_VARS.page = LPOPRO_VARS.pageDiv.innerHTML;
}

LPOPRO_CONTROL.init = function() {
	if (LPOPRO_VARS.pageDiv==null) {
		LPOPRO_CONTROL.addLoadEvent(LPOPRO_CONTROL.waitForSession);
	}
}

LPOPRO_VARS.experimentId = LPOPRO_CONTROL.readCookie('__lpopro_combinationid');
LPOPRO_VARS.timeout = setTimeout(LPOPRO_CONTROL.errhdl, LPOPRO_VARS.timeout);

/*
 * Ensures that postprocessingCallback function is invoked after the
 * replacement is done.
 */
LPOPRO_CONTROL.callPostprocessingCallback = function() {
	if (!LPOPRO_VARS.replacementDone) {
		setTimeout(LPOPRO_CONTROL.callPostprocessingCallback, 100);
		return;
	}

	LPOPRO_CONTROL.postprocessingCallback();
}


// Set this function with whatever JS should be executed after replacements.
// The function will be invoked at the end of the post-processing stage, after
// executing the page replacement and invoking whatever function was found in
// window onLoad.
//LPOPRO_CONTROL.postprocessingCallback = function() {};
