var oldDomain = document.domain;
var sites;
var handler;
var pingTimes;
var loadSpeeds;
var sorted;
var pings;
var loads;
var n;
var completions;
var loaderIndex;

function estimateServers(servers, callback) {
	sites = servers;
	handler = callback;
	n = sites.length;
	startPinging();
}

function startPinging() {
	createArrays();
	//obtainPingCookies();
	//removePingIframes();
	removeLoadIframes();
	//createPingIframes();
	startLoading();
}

function createArrays() {
	// create arrays of results
	pingTimes = new Array(n);
	loadSpeeds = new Array(n);
	sorted = new Array(n);
	// create helper array for cookies
	pings = new Array(n);
	loads = new Array(n);
	// create completions flags
	completions = new Array(n);
}

function obtainPingCookies() {
	// iterate all sites 
	for (var i = 0; i < n; i++) {
		// check ping cookies
		var c_ping = getCookie(getPingCookieName(i));
		if (c_ping == null) {
			pings[i] = -1;
		} else {
			var v = parseInt(c_ping);
			if (v == 0 || v == Number.NaN) {
				pings[i] = -1;
			} else {
				pings[i] = v;
			}
		}
		// store result if any
		if (pings[i] != -1) {
			pingTimes[i] = pings[i];
			completions[i] = 1;
		} else {
			completions[i] = 0;
		}
	}
}

function createPingIframes() {
	var newDomain = oldDomain.substring(oldDomain.indexOf(".") + 1);
	document.domain = newDomain;
	var allInCookies = true;
	for (var i = 0; i < n; i++) {
		if (pings[i] == -1) {
			allInCookies = false;
			var subframe = document.createElement("iframe");
			subframe.name = getPingIframeName(i);
			subframe.style.width = "0px";
			subframe.style.height = "0px";
			subframe.style.border = "0px";
			//subframe.style.visibility = "hidden";
			document.body.appendChild(subframe);
			subframe.src = sites[i] + "bwtest/Pinger-iframe.html";
		}
	}
	// perform a check whether all ping data are already in cookies
	if (allInCookies && checkCompletions()) {
		startLoading();
	}
}

function checkCompletions() {
	var s = 0;
	for (var i = 0; i < completions.length; i++) {
		s += completions[i];
	}
	return s == n;
}


function setPingTime(time, site) {
	for (var i = 0; i < n; i++) {
		if (sites[i].indexOf(site) >= 0) {
			pingTimes[i] = time;
			completions[i] = 1;
			if (checkCompletions()) {
				startLoading();
			}
			break;
		}
	}
}

function startLoading() {
	//removePingIframes();
	obtainLoadCookies();
	iterateLoadIframes();
}

function removePingIframes() {
	for (var i = 0; i < n; i++) {
		var ifr = document.getElementById(getPingIframeName(i));
		if (typeof ifr != 'undefined' && ifr != null) {
			document.body.removeChild(ifr);
		}
	}
}

function obtainLoadCookies() {
	var newDomain = oldDomain.substring(oldDomain.indexOf(".") + 1);
	document.domain = newDomain;
	// iterate all sites 
	for (var i = 0; i < n; i++) {
		// set cookies for ping
		//var pt = pingTimes[i];
		//setBWCookie(getPingCookieName(i), pt.toString());
		// check load cookies
		var c_load = getCookie(getLoadCookieName(i));
		if (c_load == null) {
			loads[i] = -1;
		} else {
			var f = parseFloat(c_load);
			if (f == 0.0 || f == Number.NaN) {
				loads[i] = -1;
			} else {
				loads[i] = f;
			}
		}
		// store result if any
		//if (pt != -1) {
			if (loads[i] < 0) {
				completions[i] = 0;
			} else {
				completions[i] = 1;
				loadSpeeds[i] = loads[i];
			}
		//} else {
		//	completions[i] = 1;
		//	loadSpeeds[i] = -1;
		//}
	}
}

function iterateLoadIframes() {
	loaderIndex = 0;
	startNextLoader();
}

function startNextLoader() {
	var allInCookies = true;
	while (loaderIndex < n) {
		//if (pingTimes[loaderIndex] != -1) {
			if (completions[loaderIndex] == 0) {
				allInCookies = false;
				var subframe = document.createElement("iframe");
				subframe.name = getLoadIframeName(loaderIndex);
				subframe.style.width = "0px";
				subframe.style.height = "0px";
				subframe.style.border = "0px";
				//subframe.style.visibility = "hidden";
				document.body.appendChild(subframe);
				subframe.src = sites[loaderIndex] + "bwtest/Loader-iframe.html";
				loaderIndex++;
				break;
			}
		//}
		loaderIndex++;
	}
	if (allInCookies && checkCompletions()) {
		doFinalOutput();
	}
}

function setLoadSpeed(speed, site) {
	var exp = new Date();  
	exp.setTime (exp.getTime() - 1);  
	for (var i = 0; i < n; i++) {
		if (sites[i].indexOf(site) >= 0) {
			loadSpeeds[i] = speed;
			completions[i] = 1;
			if (speed > 0) {
				setBWCookie(getLoadCookieName(i), speed.toString());
			} else {
				setBWCookie(getLoadCookieName(i), 'FAILED');
				//var name = getLoadCookieName(i);
				//var cval = "-1";
				//document.cookie = name + "=" + cval + "; expires=" + exp.toGMTString();
			}
			startNextLoader();
			break;
		}
	}
}

function doFinalOutput() {
	//var exp = new Date();  
	//exp.setTime (exp.getTime() - 1);  
	//for (var i = 0; i < sites.length; i++) {
//		if (loadSpeeds[i] > 0) {
//			setBWCookie(getLoadCookieName(i), loadSpeeds[i].toString());
//		} else {
//			var name = getLoadCookieName(i);
//			var cval = "-1";
//			document.cookie = name + "=" + cval + "; expires=" + exp.toGMTString();
//		}
//	}
	removeLoadIframes();
	sortServers();
	try {
		document.domain = oldDomain;
	} catch (e) {
		// we need try..catch for FF/Safari/Opera
	}
	handler();
}

function removeLoadIframes() {
	for (var i = 0; i < n; i++) {
		var ifr = document.getElementById(getLoadIframeName(i));
		if (typeof ifr != 'undefined' && ifr != null) {
			document.body.removeChild(ifr);
		}
	}
}


function sortServers() {
	var n = sites.length;
	sorted = new Array(n);
	for (var i = 0; i < n; i++) {
		sorted[i] = i;
	}
	for (i = 0; i < n; i++) {
		var k = sorted[i];
		var m = loadSpeeds[k];
		var index = i;
		for (var j = i + 1; j < n; j++) {
			if (loadSpeeds[sorted[j]] > m) {
				index = j;
			}
		}
		sorted[i] = index;
		sorted[index] = k;
	}
}

function getPingIframeName(i) {
	return "_emg_pinger_" + i;
}

function getLoadIframeName(i) {
	return "_emg_loader_" + i;
}


// result

function getPingTime(i) {
	return pingTimes[i];
}

function getLoadSpeed(i) {
	return loadSpeeds[i];
}

function getSortedServers() {
	return sorted;
}


// cookies

function getCookieVal (dc, offset) {  
	var endstr = dc.indexOf (";", offset);  
	if (endstr == -1) { endstr = dc.length; }
	return unescape(dc.substring(offset, endstr));
}

function getCookie (name) {  
	var arg = name + "=";  
	var alen = arg.length;  
	var dc = document.cookie;
	var clen = dc.length;
	var i = 0;  
	while (i < clen) {    
		var j = i + alen;    
		if (dc.substring(i, j) == arg) return getCookieVal (dc, j);    
		i = dc.indexOf(" ", i) + 1;    
		if (i == 0) break;   
	}  
	return null;
}

function setBWCookie (name, value) {  
	var argv = setBWCookie.arguments;  
	var argc = setBWCookie.arguments.length;  
	//var expires = (argc > 2) ? argv[2] : null;  
	var today = new Date();
	var expires = new Date();
	expires.setTime(today.getTime() + 3600000*3);
	var path = (argc > 3) ? argv[3] : null;  
	var domain = (argc > 4) ? argv[4] : null;  
	var secure = (argc > 5) ? argv[5] : false;  
	document.cookie = name + "=" + escape (value) + 
	((expires == null) ? "" : ("; expires=" + expires.toGMTString())) + 
	//((path == null) ? "" : ("; path=" + path)) +  
	"; path=/"+  
	((domain == null) ? "" : ("; domain=" + domain)) +    
	((secure == true) ? "; secure" : "");
}

function getPingCookieName(index) {
	return sites[index] + "_ping";
}

function getLoadCookieName(index) {
	return sites[index] + "_load";
}

function clearCookies(servers) {
	sites = servers;
	var exp = new Date();  
	exp.setTime (exp.getTime() - 1);  
	for (var i = 0; i < sites.length; i++) {
		var name = getPingCookieName(i);
		var cval = getCookie(name);  
		document.cookie = name + "=" + cval + "; expires=" + exp.toGMTString();
		name = getLoadCookieName(i);
		cval = getCookie(name);
		document.cookie = name + "=" + cval + "; expires=" + exp.toGMTString();
	}
}

