var __ipv6_test_objects = new Array();

function IPv6Test( site, callback_result, callback_loaded ) {
	this.site = site;						// Sitename as registered with ipv6test.nl
	this.callback_result = callback_result;	// Optional callback for end results
	this.callback_loaded = callback_loaded;	// Optional callback for image loaded event

	this.timeoutMsec = 10000;				// Timeout for 'final' result message in milliseconds
	this.hostSuffix = ".ipv6test.nl";		// Suffix to go on the IMG hostnames
	
	this.pageLoadTime = null;
	this.timeout = false;
	
	// Use a UTC timestamp + a random id as the test identifier
	var now = new Date();
	this.test_time = now.getTime() + (now.getTimezoneOffset() * 60000);
	this.test_id = Math.floor(Math.random()*Math.pow(2,31));

	// These are the results:
	this.time = new Array();
	this.time['ipv4'] = false;
	this.time['ipv6'] = false;
	this.time['dual'] = false;

	// Save this object in global array
	__ipv6_test_objects[this.test_id] = this;
}

IPv6Test.prototype.setCookie = function() {
	var now = new Date();
	var expire = new Date( now.getTime() + 86400000 );
	
	document.cookie = 'ipv6test_last_run=' + now.getTime() + ';expires=' + expire.toGMTString() + ';path=/';
}

IPv6Test.prototype.checkCookie = function() {
	var a_all_cookies = document.cookie.split( ';' );
	
	for ( i = 0; i < a_all_cookies.length; i++ ) {
		var a_temp_cookie = a_all_cookies[i].split( '=' );
		var cookie_name = a_temp_cookie[0].replace(/^\s+|\s+$/g, '');
		
		// if the extracted name matches passed check_name
		if ( cookie_name == 'ipv6test_last_run' ) {
			var cookie_value = unescape( a_temp_cookie[1].replace(/^\s+|\s+$/g, '') );
			var last_run = parseInt(cookie_value);
			
			// No number: run the test
			if (isNaN(last_run))
				return true;
			
			// Run if the last run was more than one day ago
			var now = new Date();
			return (last_run < (now.getTime() - 86400000));
		}
	}
	
	// No cookie found: run the test
	return true;
}

IPv6Test.prototype.run = function( forced ) {
	// Check the cookie to avoid running the test too often
	if (!forced && !this.checkCookie())
		return;
	
	this.writeHtml();

	// Chain the startTest call at the end of the onLoad event
	var oldonload = window.onload;
	var myself = this;
	window.onload = function() {
		if (typeof oldonload == 'function')
			oldonload();
		
		myself.startTest();
	}
}

IPv6Test.prototype.writeHtml = function() {
	// Write the HTML for the test
	document.writeln('<div style="visibility: hidden;">');
	document.writeln('<img height="1" width="1" src="" id="__ipv6wwwtest_' + this.test_id + '_ipv4Img" onload="__ipv6_test_objects[' + this.test_id + '].imageLoaded(\'ipv4\');" />');
	document.writeln('<img height="1" width="1" src="" id="__ipv6wwwtest_' + this.test_id + '_ipv6Img" onload="__ipv6_test_objects[' + this.test_id + '].imageLoaded(\'ipv6\');" />');
	document.writeln('<img height="1" width="1" src="" id="__ipv6wwwtest_' + this.test_id + '_dualImg" onload="__ipv6_test_objects[' + this.test_id + '].imageLoaded(\'dual\');" />');
	document.writeln('<img height="1" width="1" src="" id="__ipv6wwwtest_' + this.test_id + '_resultsImg" />');
	document.writeln('</div>');
}

IPv6Test.prototype.startTest = function() {
	// Initialise the start time
	this.pageLoadTime = new Date();
	
	// Start loading the images
	document.getElementById("__ipv6wwwtest_" + this.test_id + "_ipv4Img").src = "http://ipv4" + this.hostSuffix + "/trigger/img2.php?site=" + this.site + "&time=" + this.test_time + "&id=" + this.test_id;
	document.getElementById("__ipv6wwwtest_" + this.test_id + "_ipv6Img").src = "http://ipv6" + this.hostSuffix + "/trigger/img2.php?site=" + this.site + "&time=" + this.test_time + "&id=" + this.test_id;
	document.getElementById("__ipv6wwwtest_" + this.test_id + "_dualImg").src = "http://dual" + this.hostSuffix + "/trigger/img2.php?site=" + this.site + "&time=" + this.test_time + "&id=" + this.test_id;
	
	this.timeout = window.setTimeout('__ipv6_test_objects[' + this.test_id + '].sendFinalResults()', this.timeoutMsec);
}

IPv6Test.prototype.imageLoaded = function( image ) {
	// Save the timestamp and check if we are finished
	this.time[image] = new Date();
	
	if( typeof this.callback_loaded == 'function' ) {
		this.callback_loaded(image, this.getLoadTime( this.time[image] ));
		
		// Fake 'all' on 'dual'
		if( image == 'dual' )
			this.callback_loaded('all', this.getLoadTime( this.time[image] ));
	}

	this.checkFinished();
}

IPv6Test.prototype.sendResults = function(stage) {
	if( stage != 'final' ) {
		return;
	}
	
	document.getElementById("__ipv6wwwtest_" + this.test_id + "_resultsImg").src = "http://results" + this.hostSuffix + "/trigger/results2.php?site=" + this.site + "&time=" + this.test_time + "&id=" + this.test_id + "&stage=" + stage + "&timeout=" + this.timeoutMsec + "&ipv4=" + this.getLoadTime(this.time['ipv4']) + "&ipv6=" + this.getLoadTime(this.time['ipv6']) + "&dual=" + this.getLoadTime(this.time['dual']);
};

IPv6Test.prototype.getLoadTime = function(item) {
	if (item == false) {
		return "NaN";
	} else {
		return (item.getTime() - this.pageLoadTime.getTime());
	}
}

IPv6Test.prototype.checkFinished = function() {
	if ( (! this.time['ipv4']) || (! this.time['ipv6']) || (! this.time['dual']) ) {
		if (!this.timeout) {
			this.timeout = window.setTimeout('__ipv6_test_objects[' + this.test_id + '].sendFinalResults()', this.timeoutMsec);
		}
		this.sendResults('partial');
	} else {
		this.sendFinalResults();
	}
}

IPv6Test.prototype.sendFinalResults = function() {
	if (this.timeout) {
		window.clearTimeout(this.timeout);
	}
	this.sendResults('final');
	
	document.getElementById("__ipv6wwwtest_" + this.test_id + "_ipv4Img").src = "";
	document.getElementById("__ipv6wwwtest_" + this.test_id + "_ipv6Img").src = "";
	document.getElementById("__ipv6wwwtest_" + this.test_id + "_dualImg").src = "";

	this.setCookie();

	if( typeof this.callback_result == 'function' ) {
		var all_ok = (this.time['dual'] != false);
		this.callback_result(all_ok, {
			'ipv4': this.getLoadTime(this.time['ipv4']),
			'ipv6': this.getLoadTime(this.time['ipv6']),
			'dual': this.getLoadTime(this.time['dual']),
			
			// The meaning of 'all' is now replaced by 'dual'
			'all': this.getLoadTime(this.time['dual']),
			
			// Legacy stuff
			'noteredo': 'NaN',
			'6to4': 'NaN',
			'6to4and4': 'NaN',
			'teredo': 'NaN',
			'teredoand4': 'NaN'
		});
	}
}

