function roundf(fl, places) { 
  shift = Math.pow(10, places);
  return (Math.floor(fl * shift)) / shift;
}                                           

var results        = [];
var global_results = {"download":0, "upload":0, "connections":0, "ping":0};
var test_length    = 10;

var connections_sum    = 0;
var startTime;
var endTime;  
var aktiv;
//upload
var strings        = {};
var ping = 0;

build_strings();


var d_class = 'poor';
var u_class = 'poor';
var c_class = 'poor';
var p_class = 'poor';

kbyte_download = 0;
kbit_download = 0;
download_error = false;
upload_error   = false;

kbyte_upload = 0;
kbit_upload = 0;

function set_kbyte_download(value){
	kbyte_download = value;
}

function set_kbit_download (value){
	kbit_download = value;
}

function set_kbyte_upload(value){
	kbyte_upload = value;
}

function set_kbit_upload(value){
	kbit_upload = value;
}


function set_d_class(p) {
  d_class = p;
}

function set_u_class(p) {
  u_class = p;
}

function set_c_class(p) {
  c_class = p;
}
function set_p_class(p) {
  p_class = p;
}

function set_ping(p) {
  ping = p;
}

function build_string(size) {
  var o;
  var upload       = "";
  var str =  "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

  for (var i=1; i<=size; i++) {
    o = "";
    for (var p=1;p<=1024;p++) {
      o=o+str.charAt(Math.random()*61);
    }
    upload = upload + o;
  }                       
  return upload;  
}

function build_strings() {
  strings[64]    = build_string(64);
}  

function build_s(size) {
  
  if (size == 64) {
    return strings[64];
  } else {
    var mal = size / 64;
    var tmp = '';
    for(var i=0; i < mal; i++) {
      tmp = tmp + strings[64];
    }
    return tmp;
  }
}

function done_pretest(test_obj, start, size) {
  var end    = (new Date()).getTime(); 

  var duration = (end - start-82) / 1000;  
  var now = (end - startTime) / 1000;
	
	set_kbyte_upload(Math.round(size / duration));
	set_kbit_upload(kbyte_upload * 8);
	
  var prognose   = (size / (end - start) ) * (test_length - now);
  var tmp = find_nearest_size(prognose);      
  test_obj.test_method(test_obj, tmp, 1);
}        
     
function done_loading2(test_obj, start, size, i) {
  var end    = (new Date()).getTime();   
	var duration   = (end - start - 82) / 1000;
	
	var bd_byte = Math.round(size / duration);
	var bd_bit  = bd_byte * 8;
 
  if (kbit_upload < bd_bit) {
    set_kbyte_upload(bd_byte);
		set_kbit_upload(bd_bit); 
  } 
	upload_status(kbit_upload);
}

function find_nearest_size(size) {
   for(var i=200; i< 16000;) {
     i = i + 50;
     if (size < i) {
       return (i-150);
     }
   }
   return 0;
 }   

function finish_test(test_obj) {
  if(test_obj.key == "download"){
		print_download_results(test_obj);
	}
	if(test_obj.key == "upload"){
		print_upload_results(test_obj);
	}
	
	if(test_obj.key == "ping"){
		print_ping_results(test_obj);
	}
	
	if(test_obj.key == "connections"){
		print_connections_results(test_obj);
	}
}

function print_download_results(){
 	hide_indicators("download_indicator");
	
 	if(kbyte_download != 0 || kbit_download != 0){
		if(test_allowed) result_to_html("download_kbyte_value", kbyte_download);
	 	if(test_allowed)  result_to_html("download_kbit_value", kbit_download);  

		global_results["download"]  = kbit_download;
		if(test_allowed)	document.getElementById('download_bar').className = d_class;
	
		set_kbit_download(0);
		set_kbyte_download(0);
	}else if(!download_error){
		download_error = true;
		$("speed_error").innerHTML = "<div>Leider konnte bei Ihrem Test kein sinnvolles Ergebnis ermittelt werden."+
		" Dies liegt vermutlich daran, dass Sie einen Proxy-Server verwenden oder eine "+
		" Sicherheitssoftware installiert ist, beispielsweise GDATA, Kaspersky, "+
		" Zonealarm o.&Auml;. <a href='http://www.speedmeter.de/start/faq#infinity'>Mehr dazu hier</a>.</div>";
		update_progress_bar(-1, "download_progress");		
	}
};

function print_upload_results(){
 	hide_indicators("upload_indicator");
 	
 	if ( kbyte_upload > 0 || kbit_upload > 0) {
 	  
    if (test_allowed) result_to_html("upload_kbyte_value", kbyte_upload);  
    if (test_allowed)  result_to_html("upload_kbit_value", kbit_upload);
	
    global_results["upload"]  = kbit_upload;
	
    if (test_allowed) $('upload_bar').className = u_class;
	
    set_kbit_upload(0);
    set_kbyte_upload(0);
  } else {
    upload_error = true;
		$("speed_error").innerHTML = "<div>Leider konnte bei Ihrem Test kein sinnvolles Ergebnis ermittelt werden. "+
		" Dies liegt vermutlich daran, dass Sie einen Proxy-Server verwenden oder eine "+
		" Sicherheitssoftware installiert ist, beispielsweise GDATA, Kaspersky, "+
		" Zonealarm o.&Auml;. <a href='http://www.speedmeter.de/start/faq#infinity'>Mehr dazu hier</a>.</div>";
		update_progress_bar(-1, "upload_progress");
  }
}

function print_connections_results(){
 	hide_indicators("connections_indicator");
	global_results['connections'] = Math.round(60.0 * (connections_sum/test_length));
 	if(test_allowed)  result_to_html("connections_size", global_results['connections']);
	connections_status(global_results['connections']);
}

function print_ping_results(){
 	hide_indicators("ping_indicator");

  if(test_allowed){
		if(ping == 0) {
			ping0 = "&mdash;";
		}else{
			ping0 = ping;
		}
	
		new Element.update("ping_size", ping0);
	}
	ping_status(ping);
 	global_results['ping'] = ping;	
}

function preupload(test_obj, start_size) {                     
  var start = (new Date()).getTime();                    
  var url   = '/speed/upload.html?' + start_size+'&z='+start;              
  //var url   = 'http://wwwns.akamai.com/crossdomain.xml?' + start_size+'&z='+start;              
  //var url   = 'http://www.speed.io/nullbyte.html?' + start_size+'&z='+start;              
  //var url   = 'http://static.speedmeter.de/upload.html?' + start_size+'&z='+start;              

  new Ajax.Request(url, { method: 'POST', parameters: {str: strings[start_size]}, onComplete:function(){
	console.log(arguments);
    return  done_pretest(test_obj, start, start_size);
    },
	onFailure:function() {
		console.log(arguments);
	}
  });         
}

function upload_status(bandbreite) {
  var url = '/speedtest/upload_status/';
  new Ajax.Request(url, { method: 'post',   parameters: {upload: bandbreite}});  
}

function connections_status(size) {  
  var url = '/speedtest/connections_status/';
  new Ajax.Request(url, { method: 'post',   parameters: {connections: size}, onComplete:function(){
    $("connections_bar").className = c_class;
  }});  
}

function ping_status(size) {   
  var url = '/speedtest/ping_status/';
  new Ajax.Request(url, { method: 'post',   parameters: {ping: size}, onComplete:function(){
    $("ping_bar").className = p_class;
  }});  
}

function download_flash(test_obj, size, i) {
	if(deconcept.SWFObjectUtil.getPlayerVersion()["major"] >= 8){
		flashMovie.startDownloadTest();
	}else{
		$("speed_error").innerHTML = ("<div>Leider ist bei Ihnen kein Flash istalliert, weshalb der Test nicht durchgef&uuml;hrt werden konnte. <br /><a href='http://www.speedmeter.de/start/faq#installieren'>Mehr dazu hier.</a></div>");

		set_kbit_download(0);
		set_kbyte_download(0);
		download_error = true;
		update_progress_bar(100, "download_progress");
		test_allowed = false;
		
		$("test_handler").setStyle({'background-position': '0 0'}).title = "Speedtest jetzt starten!";
		$("test_handler").onclick = function(){
			test_allowed = true;
			SpeedMeterTest.init();
		};
	}
}

function flash_done_loading(duration, size) {
	if(isNaN(size) || !isFinite(size) || typeof(size) != "number"){ 
		size = 0;
	}

	set_kbit_download(size);
	set_kbyte_download(Math.round(size/8));
	var url = '/speedtest/download_status/';
  new Ajax.Request(url, { method: 'post',   parameters: {download: size}});
}

function upload(test_obj, size, i) { 
  var start = (new Date()).getTime();
  var url   = '/speed/upload.html?' + size+'&z='+start;
  
  new Ajax.Request(url, { method: 'POST', parameters: {str: build_s(size)}, onComplete:function(){
    return done_loading2(test_obj, start, size, i);
    }
  });
}

function load_connection(test_obj) { 
  var end   = (new Date()).getTime(); 
  var now = (end - startTime) / 1000.0;

  connections_sum = connections_sum + 1;
  if ((test_length - Math.round(now)) > 0  ) {
    connection(test_obj, 0);
  } 
}

function connection(test_obj, index) {
  var start = (new Date()).getTime();
  var url = '/speed/upload.html?'+start;

  new Ajax.Request(url, { method: 'post', onComplete:function(){
    return load_connection(test_obj);
    }
  });
}

function ping_request(test_obj, index) {
  var url = '/speedtest/ping';
  new Ajax.Request(url, { method: 'post' });
}

function update_progress_bar(x, progress_bar){	
	if((download_error && x == 100) || (upload_error && x == 100)){
  	$(progress_bar).style.width = 0 +'%';
	} else {
		$(progress_bar).style.width = (x+1) +'%';
	}
}  

function progress(end, start, progress_bar) { 
  now  = (new Date()).getTime();
  done = ((now - start) * 100)  / (end - start);
  update_progress_bar(done, progress_bar);
}

function show_indicators(indicator_id) {
  $(indicator_id).style.display = 'block';
} 

function hide_indicators(indicator_id) {
  $(indicator_id).style.display = 'none';
}  

function reset_text_fields(test_obj) { 

  if (typeof(test_obj.kbyte_field) != 'undefined') {
    $(test_obj.kbyte_field).innerHTML ='';
  }

  if (typeof(test_obj.kbit_field) != 'undefined') {
    $(test_obj.kbit_field).innerHTML  ='';
  }

  if (typeof(test_obj.size_field) != 'undefined') {
    $(test_obj.size_field).innerHTML  ='';  
  }
	if (typeof(test_obj.ping_field) != "undefined") {
		$(test_obj.ping_field).innerHTML  ='';  
	};
}

function result_to_html(id, result) {
  $(id).innerHTML = roundf(result,1);
}

function save_results(results) { 
  var url = '/speedtest/save_result';
  new Ajax.Request(url, { method: 'POST', parameters: results });
}

function start_tests(test_obj) {

  connections_sum = 0;
  results = [];
  download_error = false;
	upload_error = false;
  show_indicators(test_obj.indicator);

  
  startTime = (new Date()).getTime();
  endTime   = (new Date()).getTime()+( test_length * 1000 );         

  test_obj.pretest_method(test_obj);
  
  window.clearInterval(aktiv);
  
  meine_function = function() {
		
		if(test_allowed){
			if((new Date()).getTime() >= endTime){
				window.clearInterval(aktiv);   
				
				if(test_obj.next != 0) {                      
					finish_test(test_obj);
					update_progress_bar(100, test_obj.progress);  
					start_tests(test_obj.next);
				}else{
					finish_test(test_obj);                        
					update_progress_bar(100, test_obj.progress);
					save_results(global_results);
					$("test_handler").setStyle({'background-position': '0 0'}).title = "Speedtest jetzt starten!";
					$("test_handler").onclick = function(){
						test_allowed = true;
						SpeedMeterTest.init();
					};
				}           
			}else{
				progress( endTime, startTime, test_obj.progress);
			}
		}else{
			clearInterval(aktiv);
			update_progress_bar(-1, test_obj.progress);
			finish_test(test_obj);
			//$("speed_error").innerHTML = "";
		}

  };
       
  aktiv = window.setInterval("meine_function()", 1024);
} 


var SpeedMeterTest = {
	init: function(){
	  this.download_obj = {
	    "kbyte_field": "download_kbyte_value", 
	    "kbit_field" : "download_kbit_value", 
	    "indicator"  : "download_indicator", 
	    "progress"   : "download_progress",
	    "key"        : "download",
	 		"result_bar" : "download_bar",
	    "test_method": function(obj, size, index){ 
				download_flash(obj, size, index);
			},    
			 
	    "pretest_method": function(obj){ 
				download_flash(obj);
			}
	  };		

	  this.upload_obj = {
	    "kbyte_field": "upload_kbyte_value", 
	    "kbit_field" : "upload_kbit_value", 
	    "indicator"  : "upload_indicator",
	    "progress"   : "upload_progress",
	    "key"        : "upload",
	    "result_bar" : "upload_bar",
	    "test_method": function(obj, size, index){ upload(obj, size, index); },
	    "pretest_method": function(obj){ preupload(obj, 64); }
	  };


	  this.connections_obj = {
	    "indicator"  : "connections_indicator",
	    "size_field" : "connections_size",
	    "progress"   : "connections_progress",
	    "key"        : "connections",
	    "result_bar" : "connections_bar",
	    "pretest_method": function(obj, size, index){ connection(obj, index); }
	  };
		
	  this.ping_obj = {
	    "indicator"  : "ping_indicator",
	    "ping_field" : "ping_size",
	    "progress"   : "ping_progress",
	    "key"        : "ping",
	    "result_bar" : "ping_bar",
	    "pretest_method": function(obj, size, index){ ping_request(obj, index); }
	  };

		var start_object = undefined;
		var objects = [];
		
		["chkbox_download", "chkbox_upload", "chkbox_connect", "chkbox_ping"].each(function(checkbox){
			var element = $(checkbox);
			var value = element.value;
			if(element.checked){
				start_object = start_object || this[value];
				objects.push(this[value]);
			}
			
			reset_text_fields(this[value]);
			update_progress_bar(-1, this[value].progress);
			if (typeof(this[value].result_bar) != "undefined") { 
				$(this[value].result_bar).className = "none";
			};
		}.bind(this));
		
		objects.each(function(obj){
			var next_object;
			var position = objects.indexOf(obj);
			if(objects.last() == obj){
				obj.next = 0;
			}else{
				obj.next = objects[position+1];
			}
		}.bind(this));
		
		this.hideOldResults();
		
		if(start_object && test_allowed){
			$("test_handler").setStyle({'background-position': '0 -101px'}).title = "Speedtest jetzt abbrechen!";
			$("test_handler").onclick = function(){
				test_allowed = false;
				SpeedMeterTest.init();
			};
      
      global_results = {"download":0, "upload":0, "connections":0, "ping":0};
			start_tests(start_object);
		}else{
			test_allowed = false;
			$("test_handler").setStyle({'background-position': '0 0'}).title = "Speedtest jetzt starten!";
			$("test_handler").onclick = function(){
				test_allowed = true;
				SpeedMeterTest.init();
			};
		}
		
	},
	hideOldResults: function(){
		var container = $("container");
		if(container.childNodes.length > 1){
			$A(container.childNodes).each(function(element){
				if(element.nodeType == 1){
					element.style.display = "none";
				}
			});
		}
		$("speed_error").innerHTML = "";
	}
};
