/** @name stats counter logger
  * @file loggs user activity and sends client infos
  *
  * @author Tobias Zeising (tz@arsnavigandi.de, tobias.zeising@aditu.de)
  * @last_modification 04/11/2008
  * @version 0.1
  */
  
/** stats main class
  * @constructor
  */
var stats = {

	// url of the backend (target of all requests)
	base: window.location.protocol+'//'+window.location.host+window.location.pathname,
	
	// image object for sending data
	sendImg: new Image(),

	// client infos
	detect: navigator.userAgent.toLowerCase(),
	language: navigator.appName=='Netscape' ? navigator.language : navigator.browserLanguage,
	referrer:  document.referrer,
	screenWidth:  screen.width,
	screenHeight:  screen.height,
	colordepth:  screen.colorDepth,
	windowWidth:  window.innerWidth,
	windowHeight:  window.innerHeight,

	browser: null,
	version: null,
	os: null,
	os_version: null,
	
	time_start: new Date(),
	cycleId: null,

	
	/** loads and initialize the user logger
	  * @param base sets server url
	  */
	initialize: function(base) {
	
		// overwrite server url
		if(base)
			stats.base = base;
	
		// register onload event (sends duration and client infos to server)
		arscms_registerEvent( {'eventType':'click','eventObject':document,'eventFunctionName':'stats.clickEventHandler'} );
		arscms_registerEvent( {'eventType':'load','eventObject':window,'eventFunctionName':'stats.loadEventHandler'} );
	},

	
	/** encodes an param for sending in a get request
	  * @return encoded param
	  * @param param for encoding
	  */
	encode:function(e){
		if(!e || e=="undefined")
			return "";
		if(encodeURIComponent)
			return encodeURIComponent(e);
		else
			return escape(e);
	},

	
	/** search in clients userAgent field for a given string
	  * @return on success position on failure 0
	  * @param str searchstring
	  */	
	searchBrowser: function(str) {
		this.pos = navigator.userAgent.toLowerCase().indexOf(str) + 1;
		this.version = navigator.userAgent.toLowerCase().charAt(this.pos + str.length);
		return this.pos;
	},

	
	/** detects the browser and version of client
	  */		
	detectBrowser: function() {
		if(this.searchBrowser('konqueror'))
			this.browser = "Konqueror";
		else if(this.searchBrowser('safari'))
			this.browser = "Safari";
		else if(this.searchBrowser('omniweb'))
			this.browser = "OmniWeb";
		else if(this.searchBrowser('k-meleon')) {
			this.browser = "K-Meleon";
			var rv = navigator.userAgent.toLowerCase().match(/k-meleon ([\w.]+)/);
			if (rv) {
				rv = rv[0];
				this.version = rv.substr(3);
			}
		} else if(this.searchBrowser('opera'))
			this.browser = "Opera";
		else if(this.searchBrowser('webtv'))
			this.browser = "WebTV";
		else if(this.searchBrowser('icab'))
			this.browser = "iCab";
		else if(this.searchBrowser('msie'))
			this.browser = "Internet Explorer";
		else if(!this.searchBrowser('compatible')) {
			this.browser = "Netscape Navigator"
			this.version = navigator.userAgent.toLowerCase().charAt(8);
			
			if (typeof(navigator.product) != "undefined") {
				this.browser = "Mozilla";
				rv = navigator.userAgent.match(/([Mozilla ]?Fire\w+)\/([\w|\+.]+)/);
				if (rv) {
					this.browser += rv[1];
					this.version = rv[2];
				} else {
					rv = navigator.userAgent.match(/rv:([\w|\+.]+)/);
					if (rv) {
						rv = rv[0];
						this.version = rv.substr(3);
					}
				}
			}
		} else 
			this.browser = "unknown browser";
	},


	/** detect the current window size
	  */	
	detectWindowSize: function() {
		stats.windowWidth = window.innerWidth;
		stats.windowHeight = window.innerHeight;
		
		// read window size on nasty ie
		if(!window.innerWidth && document.body.offsetHeight)
			stats.windowHeight = document.body.offsetHeight;
		if (!window.innerHeight && document.body.offsetWidth)
			stats.windowWidth = document.body.offsetWidth;
		
	},


	/** detect operating system and version
	  */	
	detectOS: function() {
		var agent = navigator.userAgent.toLowerCase();
		
		// get version on windows clients
		if (agent.indexOf("win")!=-1 || agent.indexOf("16bit")!=-1) {
			if (agent.indexOf("win95")!=-1 || agent.indexOf("windows 95")!=-1)
				this.os_version = "Windows 95";
			if (agent.indexOf("win98")!=-1 || agent.indexOf("windows 98")!=-1)
				this.os_version = "Windows 98";
			if (agent.indexOf("win 9x 4.90")!=-1)
				this.os_version = "Windows ME";
			if (agent.indexOf("winnt")!=-1 || agent.indexOf("windows nt")!=-1)
				this.os_version = "Windows NT";
			if (agent.indexOf("windows nt 5.0")!=-1)
				this.os_version = "Windows 2000";
			if (agent.indexOf("windows nt 5.1")!=-1)
				this.os_version = "Windows XP";
			if (agent.indexOf("windows nt 6.0")!=-1)
				this.os_version = "Windows Vista";
			if (!this.os_version)
				this.os_version = "Unknown Windows";
		}
		
		// get operating system
		if (agent.indexOf('linux')!=-1) 
			this.os = "Linux";
		else if (agent.indexOf('x11')!=-1) 
			this.os = "Unix";
		else if (agent.indexOf('mac')!=-1) 
			this.os = "Mac"
		else if (agent.indexOf('win')!=-1) 
			this.os = "Windows"
		else 
			this.os = "unknown operating system";
	},

	
	/** sends click informations to server
	  * @param type of the click (extern, intern, ...)
	  * @param e event
	  */
	sendClick: function(type, e) {
	
		// extract event infos
		var linkInfos = stats.getEventInfos(e);
		
		// get time of click
		var time = ((new Date()).getTime() - stats.time_start.getTime());
		
		// detect current window size
		stats.detectWindowSize();
		
		// send result to server
		stats.send("?click=1&type=" + stats.encode(type) + "&x=" + linkInfos[0] + "&y=" + linkInfos[1] + "&target=" + stats.encode(linkInfos[2]) + "&time=" + time + "&ww=" + stats.windowWidth + "&wh=" + stats.windowHeight);
	},


	/** sends informations to server using an image object
	  * @param params infos for sending
	  */
	send: function(params) {
		var url = stats.base + params + "&cycleid=" + stats.cycleId + "&rdm="+Math.random() + "&op=logStats";
		
		// send via ajax
		new Ajax.Request(url, { method: 'get' });
		
		// send via img
		// stats.sendImg.src = url;
		
		// fix a bug in opera
		var t=500;
		var now=new Date();
		var stop=now.getTime()+t;
		while(now.getTime()<stop)
			var now=new Date();	
	},

	
	/** analyizes an event and extract mouse position and targetlink
	  * @return array [0 = mouse x position, 1 = mouse y position, 2 = target link]
	  * @param e event
	  */
	getEventInfos: function(e) {

		// position where mousemove fired
	    var xPos = window.event ? window.event.x : e.pageX;
		var yPos = window.event ? window.event.y : e.pageY;

	    // find out if ie runs in quirks mode
	    var docEl = (typeof document.compatMode != "undefined" && document.compatMode != "BackCompat") ? "documentElement" : "body";
		
		// for nasty ie add scroll position
		if (document.all && !document.captureEvents) {
		    xPos += document[docEl].scrollLeft;
		    yPos += document[docEl].scrollTop;
	    }
		
		// read target
		var element = e || window.event;
		var target = element.target || element.srcElement;
		return new Array(xPos, yPos, target.href);
	},

	
	/** event handler for unloading the page
	  */
	unload: function() {
		var durationStay = ((new Date()).getTime() - stats.time_start.getTime());
		
		stats.send(
			"?unload=1"
			+ "&durationstay=" + stats.encode(durationStay)
		);
	},

	
	clickEventHandler: function(e) {
		var element = e || window.event;
		var target = element.target || element.srcElement;
	
			// types for checking the links
		var downloadTypes = "7z|aac|avi|csv|doc|exe|flv|gif|gz|jpe?g|js|mp(3|4|e?g)|mov|pdf|phps|png|ppt|rar|sit|tar|torrent|txt|wma|wmv|xls|xml|zip";
		var linkTypes = "https?|ftp|telnet|ssh";
		var javascriptTypes = "javascript";
		var emailType = "mailto";
		
			// regular expression tester
		var isDownload = new RegExp("\\.(" + downloadTypes + ")$","i");
		var isLink = new RegExp("^(" + linkTypes + "):","i");
		var isEmail = new RegExp("^(" + emailType + "):","i");
		var isJavaScript = new RegExp("^(" + javascriptTypes + "):","i");
		var isInternalLink = new RegExp("^https?:\/\/(.*)" + location.host.replace(/^www\./i,""),"i");
		
			// check type of target
		if(isLink.test(target)) { // links
			if(isInternalLink.test(target)) { 
				if(isDownload.test(target)) { // download link
					stats.sendClick("download",e);
				} else {	// internal link
					stats.sendClick("intern",e);
				}
			} else { // extern link
				stats.sendClick("extern",e);
			}
		} else if(isEmail.test(target)) // mailto:
			stats.sendClick("email",e);
		else if(isJavaScript.test(target)) // javascript:
			stats.sendClick("javascript",e);
		else
			stats.sendClick("anywhere",e);
	},


	/** register event handler for clicking on a link
	  */	
	loadEventHandler: function() {
		// read cycleID from meta tags
		for (var i = 0; i < document.getElementsByTagName('meta').length; i++)
			if (document.getElementsByTagName('meta')[i].getAttribute('name') == 'cycleId')
				stats.cycleId = document.getElementsByTagName('meta')[i].getAttribute('content');
	
		// read client informations
		stats.detectWindowSize();
		stats.detectBrowser();
		stats.detectOS();
		
		// send client infos
		var durationLoad = ((new Date()).getTime() - stats.time_start.getTime());
		this.time_start = new Date();
		stats.send(
			"?infos=1"
			+ "&os=" + stats.encode(stats.os)
			+ "&osver=" + stats.encode(stats.os_version)
			+ "&browser=" + stats.encode(stats.browser)
			+ "&browserv=" + stats.encode(stats.version)
			+ "&color=" + stats.encode(stats.colordepth)
			+ "&lang=" + stats.encode(stats.language)
			+ "&referrer=" + stats.encode(stats.referrer)
			+ "&sw=" + stats.encode(stats.screenWidth)
			+ "&sh=" + stats.encode(stats.screenHeight)
			+ "&ww=" + stats.encode(stats.windowWidth)
			+ "&wh=" + stats.encode(stats.windowHeight)
			+ "&duration=" + stats.encode(durationLoad)
		);
		
	}
}
// ueber operation
stats.initialize();