/*
 * knwebstd-tools-performance: JavaScript library for network performance measurement of the Kuehne+Nagel WebStandard Framework
 * Description: see ResponseTimeMeasurementUtils.java
 *
 * Copyright (c) 2009 Kuehne+Nagel
 *
 * This code is not freeware. It may not be used for any (private or commercial) purposes except by
 * Kuehne+Nagel and its associated companies.
 */

// create namespaces
if (!window.knwebstd) {
	window.knwebstd = new Object();
}
knwebstd.responseTimeMeasurement = new Object();

knwebstd.responseTimeMeasurement._cookieName="KnWebStd_RTM";

//global variables for logging
knwebstd.responseTimeMeasurement._log = false; //activate only in local environment for debugging purposes!
knwebstd.responseTimeMeasurement._logToWindow = false; //log to popup window - activate only in local environment!
knwebstd.responseTimeMeasurement._logWindowWidth = 500;
knwebstd.responseTimeMeasurement._lastTimestamp = 0; //timestamp of last log

//global variables for measurement (data is of request creating the current page)
knwebstd.responseTimeMeasurement._correlationId = 0; //correlationId of request creating current page
knwebstd.responseTimeMeasurement._lastRequestSubmitted = 0;
knwebstd.responseTimeMeasurement._lastRequestDuration1 = 0;
knwebstd.responseTimeMeasurement._lastRequestDuration2 = 0;
knwebstd.responseTimeMeasurement._lastRequestAjax = new Array(); //measurements of subsequent ajax requests

// set the correlationId of the request creating the current page
knwebstd.responseTimeMeasurement.setCorrelationId = function(correlationId) {
	knwebstd.responseTimeMeasurement.log("set _correlationId="+correlationId);
	if(correlationId == null || correlationId == '' || isNaN(correlationId)) {
		knwebstd.responseTimeMeasurement._correlationId = 0;
	} else {
		knwebstd.responseTimeMeasurement._correlationId = correlationId;
	}
	//reset cookie as early as possible to prevent using the request submit time twice
	knwebstd.responseTimeMeasurement.deleteCookie();
}

// set the request submit time (when the request that resulted in this page was sent (client local time))
knwebstd.responseTimeMeasurement.setRequestSubmitTime = function(requestSubmitTime) {
	knwebstd.responseTimeMeasurement._lastRequestSubmitted = requestSubmitTime;
	knwebstd.responseTimeMeasurement.log("set _lastRequestSubmitted = " + requestSubmitTime);
}

// take the first measurement
knwebstd.responseTimeMeasurement.measureFirstResponseDuration = function() {
	knwebstd.responseTimeMeasurement.log("measureFirstResponseDuration");
	if (knwebstd.responseTimeMeasurement._lastRequestSubmitted != null &&
			!isNaN(knwebstd.responseTimeMeasurement._lastRequestSubmitted) &&
			knwebstd.responseTimeMeasurement._lastRequestSubmitted > 0) {
		knwebstd.responseTimeMeasurement._lastRequestDuration1 = knwebstd.responseTimeMeasurement.getTimestamp()-knwebstd.responseTimeMeasurement._lastRequestSubmitted;
	} else {
		knwebstd.responseTimeMeasurement._lastRequestDuration1 = 0;
	}
	knwebstd.responseTimeMeasurement.log("_lastRequestDuration1: " + knwebstd.responseTimeMeasurement._lastRequestDuration1);
}

// take the second measurement
knwebstd.responseTimeMeasurement.measureSecondResponseDuration = function() {
	knwebstd.responseTimeMeasurement.log("measureSecondResponseDuration");
	if (knwebstd.responseTimeMeasurement._lastRequestSubmitted != null &&
			!isNaN(knwebstd.responseTimeMeasurement._lastRequestSubmitted) &&
			knwebstd.responseTimeMeasurement._lastRequestSubmitted > 0) {
		knwebstd.responseTimeMeasurement._lastRequestDuration2 = knwebstd.responseTimeMeasurement.getTimestamp()-knwebstd.responseTimeMeasurement._lastRequestSubmitted;
	} else {
		knwebstd.responseTimeMeasurement._lastRequestDuration2 = 0;
	}
	knwebstd.responseTimeMeasurement.log("_lastRequestDuration2: " + knwebstd.responseTimeMeasurement._lastRequestDuration2);
}

// sets the request submit time in a cookie
knwebstd.responseTimeMeasurement.performOnExit = function() {
	knwebstd.responseTimeMeasurement.log("");
	knwebstd.responseTimeMeasurement.log("executing performOnExit");
	knwebstd.responseTimeMeasurement.setCookie(knwebstd.responseTimeMeasurement.getTimestamp());
}

// initialize the event handlers
knwebstd.responseTimeMeasurement.setupResponseTimeMeasurement = function() {
	window.onbeforeunload = knwebstd.responseTimeMeasurement.performOnExit;
	$().ajaxSend(function() {
		//delete cookie on ajax requests, can't be measured
		knwebstd.responseTimeMeasurement.deleteCookie();
		knwebstd.responseTimeMeasurement.log("deleted cookie for ajax-request");
	});
}

// ************************************* helper functions **************************************

// get current time in ms
knwebstd.responseTimeMeasurement.getTimestamp = function (){
	return new Date().getTime();
}

// deletes the cookie (sets it to zeros)
knwebstd.responseTimeMeasurement.deleteCookie = function() {
	knwebstd.responseTimeMeasurement.log("delete cookie");
	// TODO adapt json format
	var cookie = '{"time":{"correlationId":0,"submitted":0,"duration1":0,"duration2":0}}';
	document.cookie = knwebstd.responseTimeMeasurement._cookieName + "=" + encodeURIComponent(cookie) + ";expires=Thu, 01-Jan-1970 00:00:01 GMT";
}

/**
 * Store measurement data of an ajax request to be attached to the current measurement
 */
 knwebstd.responseTimeMeasurement.addAjaxMeasurement = function(measurement){
 	// do not save more than 20 entries to limit the data volume
 	if(knwebstd.responseTimeMeasurement._lastRequestAjax.length < 20){
    knwebstd.responseTimeMeasurement._lastRequestAjax.push(measurement);
    measurement.submitted = 0; // this information is not needed
 	}
 }

/**
 * Store measurement data in a cookie that is read and logged by the server
 *
 * Outgoing cookie will be set as json representation of the measured times of this request and its subsequent ajax requests.
 */
 knwebstd.responseTimeMeasurement.setCookie = function(timestamp) {
  var cookieName = knwebstd.responseTimeMeasurement._cookieName;
  var cookie = '{"time":{';
  cookie += '"correlationId":';
  cookie += knwebstd.responseTimeMeasurement._correlationId;
  cookie += ',"submitted":';
  cookie += timestamp;
  cookie += ',"duration1":';
  cookie += knwebstd.responseTimeMeasurement._lastRequestDuration1;
  cookie += ',"duration2":';
  cookie += knwebstd.responseTimeMeasurement._lastRequestDuration2;
  var subMeasurements = knwebstd.responseTimeMeasurement._lastRequestAjax;
  if(subMeasurements.length > 0){
  	cookie += ',"ajax":{"time":['
  	for(sub in subMeasurements){
  		var measurement = subMeasurements[sub];
  		cookie += '{"correlationId":';
		  cookie += measurement.correlationId;
		  cookie += ',"submitted":';
		  cookie += measurement.submitted;
		  cookie += ',"duration1":';
		  cookie += measurement.duration1;
		  cookie += ',"duration2":';
		  cookie += measurement.duration2;
		  cookie += '}';
		  if(sub < (subMeasurements.length - 1)){
		  	cookie += ',';
		  }
  	}
  	cookie += ']}';
  }
  cookie += '}}';
  //let cookie expire in 5 sec, don't want it longer then time needed to send request. Otherwise it will still be written when page is closed!
  var expires = new Date();
  expires.setTime(knwebstd.responseTimeMeasurement.getTimestamp()+5*1000);
  document.cookie = cookieName + "=" + encodeURIComponent(cookie) + ";expires=" + expires.toGMTString();
  knwebstd.responseTimeMeasurement.log("set cookie " + cookieName  + " to: " + cookie);
}

/**
 * Log a message to the a console
 * If Firefox with Firebug Plugin is found, log to Firebug console
 * Alternatively, the output can be directed to a popup window that will maintain the info across requests
 *
 * @param msg string to be logged
 */
 knwebstd.responseTimeMeasurement.log = function(msg) {
	if(knwebstd.responseTimeMeasurement._log == true) {
		var currentTimestamp = knwebstd.responseTimeMeasurement.getTimestamp();
		var timeSinceLastLog = currentTimestamp - knwebstd.responseTimeMeasurement._lastTimestamp;
		var timeCode = currentTimestamp + " (" + timeSinceLastLog + "): ";
		knwebstd.responseTimeMeasurement._lastTimestamp = currentTimestamp;

		if(window.console) {
			window.console.log(timeCode + msg);
		}
		if(knwebstd.responseTimeMeasurement._logToWindow == true) {
			height = screen.availHeight - 30;
			left = screen.availWidth - knwebstd.responseTimeMeasurement._logWindowWidth - 10;
			var logWindow = window.open("", "log_window", "scrollbars=yes,resizable=yes,width=" + knwebstd.responseTimeMeasurement._logWindowWidth +
					",height=" + height + ",left=" + left + ",top=0");
			clear = "<span onclick='document.body.innerHTML=" + '"' + " " + '"' + ";'>[X] </span>";
			logWindow.document.write(clear + timeCode + msg + "<br>");
		}
	}
}
