/**
 * IreusHandler (Pseudo Class Definition)
 */
function IreusHandler()
{
	/**
	 * Base URL for IREUS Recommendation Service
	 * 
	 * @var string
	 * @scope private
	 */
	var servleturl = window.location.protocol + '//www.ireus.net/ireus-server';
	
	/**
	 * Request format version (Deprecated)
	 *  
	 * @var string
	 * @scope private
	 */
	var version = '1.2';
	
	/**
	 * Link observer
	 * 
	 * @var object
	 * @scope private
	 */
	var observer;

	
	/**
	 * Executes IREUS events
	 * 
	 * @scope public
	 * @param array ireus_events (array of ireus parameter objects)
	 * @return void
	 */
	this.call = function(ireus_events)
	{
		getClicks(ireus_events);
		
		for (var i = 0; i < ireus_events.length; i++)
		{
			sendEvent(ireus_events[i]);
		}
		
		observer = window.setInterval('IreusHandler.startObserver()', 500);
	};
	
	
	/**
	 * Forwards user recommendations to a userfunction or adds them to document dom
	 * 
	 * @scope public
	 * @param string result (recommendations result string)
	 * @return void
	 */
	this.displayUserRecomms = function(result)
	{
		if ((typeof ireus_userfunc_displayUserRecomms) == 'function'
		) {
			ireus_userfunc_displayUserRecomms(result);
		}
		else
		{
			document.getElementById('ireus_userrecomm').innerHTML = result.replace(/%SID%/g,ireus['sid']);
		}
	};
	
	
	/**
	 * Forwards recommendations to a userfunction or adds them to document dom
	 * 
	 * @scope public
	 * @param string result (recommendations result string)
	 * @return void
	 */
	this.displayProductRecomms = function(result)
	{
		if ((typeof ireus_userfunc_displayProductRecomms) == 'function'
		) {
			ireus_userfunc_displayProductRecomms(result);
		}
		else
		{
			document.getElementById('ireus_recomm').innerHTML = result.replace(/%SID%/g, ireus['sid']);
		}
	};
	
	
	/**
	 * Starts link observation
	 * 
	 * @scope public
	 * @return void
	 */
	this.startObserver = function()
	{
		function observe(event)
		{
			if (!event) 
				var event = window.event;
			var target = event.target || event.srcElement;
			
			var link = getLinkElement(target);
			
			if (link
			) {
				var linkparts = link.href.split('#');
				if (linkparts[0].search(/ireusocl=1/) == -1
				) {
					if (linkparts[0].search(/\?/) == -1)
						linkparts[0] += '?ireusocl=1';
					else
						linkparts[0] += '&ireusocl=1';
				}
				if ((typeof linkparts[1]) != 'undefined'
				) {
					link.href = linkparts[0] + '#' + linkparts[1];
				}
				else
				{
					link.href = linkparts[0];
				}
				document.cookie = 'ireus_ocl=1;;path=/';
			}
			
			if (ireus['debug'])
				alert('IREUS Recommendation "' + link.href + '" has been clicked!');
		}
		
		
		function getLinkElement(target)
		{
			if (target.tagName != 'A')
			{
				var parent = target.parentNode;
				if (parent.id != null
					&& parent.id != 'ireus_userrecomm'
					&& parent.id != 'ireus_recomm'
				) {
					target = getLinkElement(parent);
				}
				else
				{
					return false;
				}
			}
			
			return target;
		}


		var userrecomms = document.getElementById('ireus_userrecomm');
		var recomms = document.getElementById('ireus_recomm');
		if ((userrecomms != null && userrecomms.hasChildNodes())
			|| (recomms != null && recomms.hasChildNodes())
		) {
			window.clearInterval(observer);
			
			if (userrecomms
			) {
				var links = userrecomms.getElementsByTagName('A');
				for (var i=0; i<links.length; i++)
				{
					if(links[i].addEventListener
					) {
						links[i].addEventListener('click', observe, false);
					} 
					else if (links[i].attachEvent
					) {
						links[i].attachEvent('onclick', observe);
					} 
					else if (links[i].onclick = null
					) {
						links[i].onclick = observe;
					}
				}
			}
			
			if (recomms
			) {
				var links = recomms.getElementsByTagName('A');
				for (var i=0; i<links.length; i++)
				{
					if(links[i].addEventListener
					) {
						links[i].addEventListener('click', observe, false);
					} 
					else if (links[i].attachEvent
					) {
						links[i].attachEvent('onclick', observe);
					} 
					else if (links[i].onclick = null
					) {
						links[i].onclick = observe;
					}
				}
			}
		}
	};

	
	/**
	 * Add click event
	 * 
 	 * @scope private
	 * @return void
	 */
	function getClicks(ireus_events)
	{
		var params = document.location.search;
		var cookie = document.cookie;
		if ((params.search(/ireusocl=1/) > -1
			 || cookie.search('ireus_ocl=1') > -1
			)
			&& (ireus_events[0]['e'] == 'product'
			    || ireus_events[0]['e'] == 'recomm'
		    )
		) {
			if((typeof ireus_events[0]) != 'undefined'
			   && ireus_events[0]['pid'] != null
			) {
				ireus_events.unshift(
					{
						"reid":ireus_events[0]['reid'],
						"sid":ireus_events[0]['sid'],
						"uid":ireus_events[0]['uid'],
						"pid":ireus_events[0]['pid'],
						"e":"recommendationclicked"
					}
				);
			}
		}
		
		document.cookie = 'ireus_ocl=0;;path=/';
	}

	
	/**
	 * Sends requests to IREUS recommendation service
	 * 
	 * @scope private
	 * @param array ireus_events (array of ireus parameter objects)
	 * @return void
	 */
	function sendEvent(params)
	{
		var requestURL = '';
		
		params = handleSession(params);
		requestURL = loadParameters(params);
		
		if (ireus['debug'])
			alert('Request URL: ' + requestURL.replace(/&amp;/g, '&'));
		document.write('<script type="text/javascript" src ="' + requestURL + '" charset="utf-8"><\/script>');
	};
	
	
	/**
	 * Implementation of trim functionality
	 * 
	 * @scope private
	 * @param string string (string to trim)
	 * @return string
	 */
	function trim(string)
	{
		return string.replace(/^\s+/g, '').replace(/\s+$/g, '');
	};

	
	/**
	 * Creates REST parameter and url parameter strings
	 * 
	 * @scope private
	 * @param object ireus (request parameters)
	 * @return object ireus (request parameters)
	 */
	function loadParameters(ireus)
	{
		var requestUrlPart = '';
		var requestParameters = '';
		
		// Change IREUS 1.0 parameters to IREUS 2.0
		if (typeof (ireus['e']) != 'undefined'
		) {
			if (ireus['e'] == 'recomm'
			) {
				ireus['e'] = 'product';
			}
			if (typeof (ireus['cid']) != 'undefined'
			) {
				if ((ireus['e'] == 'userrecomm')
					 && ireus['cid'] != null 
					 && ireus['cid'] != 0
					 && ireus['cid'] != ''
				) {
					ireus['e'] = 'user';
				}
				else if (ireus['e'] != 'user')
				{
					ireus['e'] = 'home';
				}
			}
			else if (ireus['e'] == 'userrecomm'
			) {
				ireus['e'] = 'home';
			}
		}

		// Create parameters
		if (typeof (ireus['reid']) != "undefined")
			requestUrlPart += '/res/' + trim(ireus['reid']);
		if (typeof (ireus['e']) != "undefined") {
			if (ireus['e'] == 'product' || ireus['e'] == 'user' || ireus['e'] == 'home')
				requestUrlPart += '/recomm/' + ireus['e'];
			else if (ireus['e'] == 'basket' 
				     || ireus['e'] == 'order' 
				     || ireus['e'] == 'recommendationclicked')
				requestUrlPart += '/event/' + ireus['e'];
		}
		if (typeof (ireus['hsid']) != "undefined")
			requestUrlPart += '/sid/' + ireus['hsid'];
		if (typeof (ireus['huid']) != "undefined")
			requestParameters += 'userID=' + ireus['huid'] + '&amp;';
		if (typeof (ireus['pid']) != "undefined") {
			if (ireus['pid'] == null)
				ireus['pid'] = '';
			if (ireus['e'] == 'recommendationclicked') {
				requestUrlPart += '/pid/' + ireus['pid'];
			} else {
				requestParameters += 'itemid=' + ireus['pid'] + '&amp;';
			}
		}
		if (typeof (ireus['pids']) != "undefined") {
			if (ireus['pids'] == null)
				ireus['pids'] = '';
			requestParameters += 'itemids=' + ireus['pids'] + '&amp;';
		}
		if (typeof (ireus['qty']) != "undefined") {
			if (ireus['qty'] == null)
				ireus['qty'] = '';
			requestParameters += 'quantity=' + ireus['qty'] + '&amp;';
		}
		if (typeof (ireus['cid']) != "undefined") {
			if (ireus['cid'] == null)
				ireus['cid'] = '';
			requestParameters += 'categoryid=' + ireus['cid'] + '&amp;';
		}
		if (typeof (ireus['debug']) != "undefined")
			requestParameters += 'debug=' + ireus['debug'] + '&amp;';
		requestParameters += 'version=' + version;
		
		return servleturl + requestUrlPart + '?' + requestParameters;
	};

	
	/**
	 * IREUS Session handling
	 * 
	 * @scope private
	 * @param object ireus (request parameters)
	 * @return object ireus (request parameters)
	 */
	function handleSession(ireus)
	{
		// cookie name
		var cname = 'ireus_uid';

		if (ireus['sid'] == null)
			ireus['sid'] = '';
		if (ireus['uid'] == null)
			ireus['uid'] = '';

		var cpos = document.cookie.search(cname);
		if (!ireus['sid_len'])
			ireus['sid_len'] = 10;

		if (cpos == -1 || cpos == 'undefined') {
			if (ireus['sid'].length < ireus['sid_len']
					|| ireus['sid'] == ireus['sid_pattern']) {
				var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
						.split('');
				var iuid = [];
				for ( var i = 0; i < 32; i++)
					iuid[i] = chars[0 | Math.random() * chars.length];
				ireus['hsid'] = iuid.join('');
				document.cookie = cname + '=' + ireus['hsid'] + ';;path=/';
				if (!document.cookie)
					ireus['hsid'] = MD5(ireus['sid']);
			} else {
				ireus['hsid'] = MD5(ireus['sid']);
				document.cookie = cname + '=' + ireus['hsid'] + ';;path=/';
			}
		} else {
			var c = document.cookie;
			var start = c.search(cname) + cname.length + 1;
			ireus['hsid'] = c.substring(start, start + 32);
		}

		if ((typeof ireus['uid']) != 'undefined')
			if (ireus['uid'] == '' || ireus['uid'] == 0)
				ireus['huid'] = ireus['hsid'];
			else
				ireus['huid'] = MD5(ireus['uid']);
		else
			ireus['huid'] = ireus['hsid'];

		return ireus;
	};
		
	
	/**
	 * MD5 (Message-Digest Algorithm) http://www.webtoolkit.info/
	 * 
	 * @scope private
	 * @param string string (string to hash)
	 * @return string (hashed string)
	 */
	function MD5(string)
	{
		function RotateLeft(lValue, iShiftBits) {
			return (lValue << iShiftBits) | (lValue >>> (32 - iShiftBits));
		}

		function AddUnsigned(lX, lY) {
			var lX4, lY4, lX8, lY8, lResult;
			lX8 = (lX & 0x80000000);
			lY8 = (lY & 0x80000000);
			lX4 = (lX & 0x40000000);
			lY4 = (lY & 0x40000000);
			lResult = (lX & 0x3FFFFFFF) + (lY & 0x3FFFFFFF);
			if (lX4 & lY4) {
				return (lResult ^ 0x80000000 ^ lX8 ^ lY8);
			}
			if (lX4 | lY4) {
				if (lResult & 0x40000000) {
					return (lResult ^ 0xC0000000 ^ lX8 ^ lY8);
				} else {
					return (lResult ^ 0x40000000 ^ lX8 ^ lY8);
				}
			} else {
				return (lResult ^ lX8 ^ lY8);
			}
		}

		function F(x, y, z) {
			return (x & y) | ((~x) & z);
		}
		function G(x, y, z) {
			return (x & z) | (y & (~z));
		}
		function H(x, y, z) {
			return (x ^ y ^ z);
		}
		function I(x, y, z) {
			return (y ^ (x | (~z)));
		}

		function FF(a, b, c, d, x, s, ac) {
			a = AddUnsigned(a, AddUnsigned(AddUnsigned(F(b, c, d), x), ac));
			return AddUnsigned(RotateLeft(a, s), b);
		}
		;

		function GG(a, b, c, d, x, s, ac) {
			a = AddUnsigned(a, AddUnsigned(AddUnsigned(G(b, c, d), x), ac));
			return AddUnsigned(RotateLeft(a, s), b);
		}
		;

		function HH(a, b, c, d, x, s, ac) {
			a = AddUnsigned(a, AddUnsigned(AddUnsigned(H(b, c, d), x), ac));
			return AddUnsigned(RotateLeft(a, s), b);
		}
		;

		function II(a, b, c, d, x, s, ac) {
			a = AddUnsigned(a, AddUnsigned(AddUnsigned(I(b, c, d), x), ac));
			return AddUnsigned(RotateLeft(a, s), b);
		}
		;

		function ConvertToWordArray(string) {
			var lWordCount;
			var lMessageLength = string.length;
			var lNumberOfWords_temp1 = lMessageLength + 8;
			var lNumberOfWords_temp2 = (lNumberOfWords_temp1 - (lNumberOfWords_temp1 % 64)) / 64;
			var lNumberOfWords = (lNumberOfWords_temp2 + 1) * 16;
			var lWordArray = Array(lNumberOfWords - 1);
			var lBytePosition = 0;
			var lByteCount = 0;
			while (lByteCount < lMessageLength) {
				lWordCount = (lByteCount - (lByteCount % 4)) / 4;
				lBytePosition = (lByteCount % 4) * 8;
				lWordArray[lWordCount] = (lWordArray[lWordCount] | (string
						.charCodeAt(lByteCount) << lBytePosition));
				lByteCount++;
			}
			lWordCount = (lByteCount - (lByteCount % 4)) / 4;
			lBytePosition = (lByteCount % 4) * 8;
			lWordArray[lWordCount] = lWordArray[lWordCount]
					| (0x80 << lBytePosition);
			lWordArray[lNumberOfWords - 2] = lMessageLength << 3;
			lWordArray[lNumberOfWords - 1] = lMessageLength >>> 29;
			return lWordArray;
		}
		;

		function WordToHex(lValue) {
			var WordToHexValue = "", WordToHexValue_temp = "", lByte, lCount;
			for (lCount = 0; lCount <= 3; lCount++) {
				lByte = (lValue >>> (lCount * 8)) & 255;
				WordToHexValue_temp = "0" + lByte.toString(16);
				WordToHexValue = WordToHexValue
						+ WordToHexValue_temp.substr(
								WordToHexValue_temp.length - 2, 2);
			}
			return WordToHexValue;
		}
		;

		function Utf8Encode(string) {
			string = string.replace(/\r\n/g, "\n");
			var utftext = "";

			for ( var n = 0; n < string.length; n++) {
				var c = string.charCodeAt(n);
				if (c < 128) {
					utftext += String.fromCharCode(c);
				} else if ((c > 127) && (c < 2048)) {
					utftext += String.fromCharCode((c >> 6) | 192);
					utftext += String.fromCharCode((c & 63) | 128);
				} else {
					utftext += String.fromCharCode((c >> 12) | 224);
					utftext += String.fromCharCode(((c >> 6) & 63) | 128);
					utftext += String.fromCharCode((c & 63) | 128);
				}
			}
			return utftext;
		}
		;

		var x = Array();
		var k, AA, BB, CC, DD, a, b, c, d;
		var S11 = 7, S12 = 12, S13 = 17, S14 = 22;
		var S21 = 5, S22 = 9, S23 = 14, S24 = 20;
		var S31 = 4, S32 = 11, S33 = 16, S34 = 23;
		var S41 = 6, S42 = 10, S43 = 15, S44 = 21;

		string = Utf8Encode(string);

		x = ConvertToWordArray(string);

		a = 0x67452301;
		b = 0xEFCDAB89;
		c = 0x98BADCFE;
		d = 0x10325476;

		for (k = 0; k < x.length; k += 16) {
			AA = a;
			BB = b;
			CC = c;
			DD = d;
			a = FF(a, b, c, d, x[k + 0], S11, 0xD76AA478);
			d = FF(d, a, b, c, x[k + 1], S12, 0xE8C7B756);
			c = FF(c, d, a, b, x[k + 2], S13, 0x242070DB);
			b = FF(b, c, d, a, x[k + 3], S14, 0xC1BDCEEE);
			a = FF(a, b, c, d, x[k + 4], S11, 0xF57C0FAF);
			d = FF(d, a, b, c, x[k + 5], S12, 0x4787C62A);
			c = FF(c, d, a, b, x[k + 6], S13, 0xA8304613);
			b = FF(b, c, d, a, x[k + 7], S14, 0xFD469501);
			a = FF(a, b, c, d, x[k + 8], S11, 0x698098D8);
			d = FF(d, a, b, c, x[k + 9], S12, 0x8B44F7AF);
			c = FF(c, d, a, b, x[k + 10], S13, 0xFFFF5BB1);
			b = FF(b, c, d, a, x[k + 11], S14, 0x895CD7BE);
			a = FF(a, b, c, d, x[k + 12], S11, 0x6B901122);
			d = FF(d, a, b, c, x[k + 13], S12, 0xFD987193);
			c = FF(c, d, a, b, x[k + 14], S13, 0xA679438E);
			b = FF(b, c, d, a, x[k + 15], S14, 0x49B40821);
			a = GG(a, b, c, d, x[k + 1], S21, 0xF61E2562);
			d = GG(d, a, b, c, x[k + 6], S22, 0xC040B340);
			c = GG(c, d, a, b, x[k + 11], S23, 0x265E5A51);
			b = GG(b, c, d, a, x[k + 0], S24, 0xE9B6C7AA);
			a = GG(a, b, c, d, x[k + 5], S21, 0xD62F105D);
			d = GG(d, a, b, c, x[k + 10], S22, 0x2441453);
			c = GG(c, d, a, b, x[k + 15], S23, 0xD8A1E681);
			b = GG(b, c, d, a, x[k + 4], S24, 0xE7D3FBC8);
			a = GG(a, b, c, d, x[k + 9], S21, 0x21E1CDE6);
			d = GG(d, a, b, c, x[k + 14], S22, 0xC33707D6);
			c = GG(c, d, a, b, x[k + 3], S23, 0xF4D50D87);
			b = GG(b, c, d, a, x[k + 8], S24, 0x455A14ED);
			a = GG(a, b, c, d, x[k + 13], S21, 0xA9E3E905);
			d = GG(d, a, b, c, x[k + 2], S22, 0xFCEFA3F8);
			c = GG(c, d, a, b, x[k + 7], S23, 0x676F02D9);
			b = GG(b, c, d, a, x[k + 12], S24, 0x8D2A4C8A);
			a = HH(a, b, c, d, x[k + 5], S31, 0xFFFA3942);
			d = HH(d, a, b, c, x[k + 8], S32, 0x8771F681);
			c = HH(c, d, a, b, x[k + 11], S33, 0x6D9D6122);
			b = HH(b, c, d, a, x[k + 14], S34, 0xFDE5380C);
			a = HH(a, b, c, d, x[k + 1], S31, 0xA4BEEA44);
			d = HH(d, a, b, c, x[k + 4], S32, 0x4BDECFA9);
			c = HH(c, d, a, b, x[k + 7], S33, 0xF6BB4B60);
			b = HH(b, c, d, a, x[k + 10], S34, 0xBEBFBC70);
			a = HH(a, b, c, d, x[k + 13], S31, 0x289B7EC6);
			d = HH(d, a, b, c, x[k + 0], S32, 0xEAA127FA);
			c = HH(c, d, a, b, x[k + 3], S33, 0xD4EF3085);
			b = HH(b, c, d, a, x[k + 6], S34, 0x4881D05);
			a = HH(a, b, c, d, x[k + 9], S31, 0xD9D4D039);
			d = HH(d, a, b, c, x[k + 12], S32, 0xE6DB99E5);
			c = HH(c, d, a, b, x[k + 15], S33, 0x1FA27CF8);
			b = HH(b, c, d, a, x[k + 2], S34, 0xC4AC5665);
			a = II(a, b, c, d, x[k + 0], S41, 0xF4292244);
			d = II(d, a, b, c, x[k + 7], S42, 0x432AFF97);
			c = II(c, d, a, b, x[k + 14], S43, 0xAB9423A7);
			b = II(b, c, d, a, x[k + 5], S44, 0xFC93A039);
			a = II(a, b, c, d, x[k + 12], S41, 0x655B59C3);
			d = II(d, a, b, c, x[k + 3], S42, 0x8F0CCC92);
			c = II(c, d, a, b, x[k + 10], S43, 0xFFEFF47D);
			b = II(b, c, d, a, x[k + 1], S44, 0x85845DD1);
			a = II(a, b, c, d, x[k + 8], S41, 0x6FA87E4F);
			d = II(d, a, b, c, x[k + 15], S42, 0xFE2CE6E0);
			c = II(c, d, a, b, x[k + 6], S43, 0xA3014314);
			b = II(b, c, d, a, x[k + 13], S44, 0x4E0811A1);
			a = II(a, b, c, d, x[k + 4], S41, 0xF7537E82);
			d = II(d, a, b, c, x[k + 11], S42, 0xBD3AF235);
			c = II(c, d, a, b, x[k + 2], S43, 0x2AD7D2BB);
			b = II(b, c, d, a, x[k + 9], S44, 0xEB86D391);
			a = AddUnsigned(a, AA);
			b = AddUnsigned(b, BB);
			c = AddUnsigned(c, CC);
			d = AddUnsigned(d, DD);
		}
		;
		var temp = WordToHex(a) + WordToHex(b) + WordToHex(c) + WordToHex(d);
		return temp.toLowerCase();
	};
};


/**
 * Start processing
 */
if (typeof (ireus_events) != "undefined"
) {
	var IreusHandler = new IreusHandler();
	IreusHandler.call(ireus_events);
}