var xmlHttp = null;
var wtd = "";
var setAjaxTimer = false;
var timerInterval = 200;
var timerAjax = null;
var timerCounter = 0;	//for plot thumbmail
var timerCount = 5;	//refresh plot thumbnail every 5 timerInterval
var lastState = "";
var startTime = "";
var results = "";

function trim(str)
{
   return str.replace(/^\s*|\s*$/g,"");
}
function GetItem(id)
{
	if(document.layers){
		return document.layer[id];
	}
	if(document.all){
		return document.all[id];
	}
	if(!document.all && document.getElementById){
		return document.getElementById(id);
	}
	return false;
}

function GetItems(id)
{
//	document.getElementByName() will return an array of the objects if it's radio buttons
//	document.getElementById() will only return the first object of an array if it's radio buttons
	if(document.getElementsByName){
		return document.getElementsByName(id);
	}
	if(document.layers){
		return document.layers[id];
	}
	if(document.all){
		return document.all[id];
	}
}

function EnableItem(id, enabled)
{
	control = GetItem(id);
	if(control) control.disabled = !enabled;
}

function DisableItem(id)
{
	control = GetItem(id);
	if(control) control.disabled = true;
}

function SetItemCaption(id, caption)
{
	control = GetItem(id);
	if(control) control.value = caption;
}

function SetItemReadonly(id, readonly)
{
	control = GetItem(id);
	if(control) control.readonly = readonly;
}

function ValidateItem(id, illegalValue, msg)
{
	control = GetItem(id);
	if (!control) {
		alert("Invalid control: " & id);
		return false;
	}
	if (trim(control.value) == "" || trim(control.value) == illegalValue) {
		alert(msg);
		control.focus();
		return false;
	}
	return true;
}

function ValidateForm()
{
	if(!ValidateItem("input", "", "Please give a .zip file to upload.")) return false;
	control = GetItem("input");
	str = trim(control.value);
	idx = str.toLowerCase().lastIndexOf(".zip");
	if(idx+4!=str.length) {
		alert("An uploadable input file has to be a .zip file.");
		control.focus();
		return false;
	}
	return true;
}

window.onerror = null;
function help(str) {
	var URL = "help.php?h=";
	URL += str;
	var window1 = open(URL, "apHelp", 
		"width=400,height=440,directories=no,location=no,menubar=no,resizeable=no,scrollbars=yes,status=no,toolbar=no");
	window1.focus();
}

//strContent is separated by "[[[_*_]]]", and there is only one pair of key and value
function GetValue2(strContent, strKey)
{
	var sep = "\t";
	if(strContent.indexOf(sep)<0) {
		return false;
	}
	var strs = strContent.split(sep);
	if(strs[0].toUpperCase()==strKey.toUpperCase()) {
		return strs[1];
	}
	else {
		return false;
	}
}

//pairs of key and value are separated by "{{{_*_}}}"
function GetValue(strContent, strKey)
{
	var sep = "\n";
	if(strContent.indexOf(sep)<0) {
		return GetValue2(strContent, strKey);
	}
	else {
		var strs = strContent.split(sep);
		for(var i=0; i<strs.length; i++) {
			val = GetValue2(strs[i], strKey);
			if(val) {
				return val;
			}
		}
	}
	return false;
}

function EnableRadio(id, enabled)
{
	control = GetItems(id);
	if(control) {
		for(i=0; i<control.length; i++) {
			control[i].disabled = !enabled;
		}
	}
}

function EnableControls(state)
{
	if(state!="" && state==lastState) return;
	lastState = state;

	EnableItem("downloadBtn", state=="done");
	EnableItem("startBtn", state!="idle" && state!="busy" && state!="");
	EnableItem("stopBtn", state=="busy");
	EnableItem("plotBtn", false);

	//references
	EnableRadio("prefCheck", state!="busy" && state!="");
	EnableItem("pref", state!="busy" && state!="");

	//parameters
	EnableItem("maxits", state!="busy" && state!="");
	EnableItem("convits", state!="busy" && state!="");
	EnableItem("dampfact", state!="busy" && state!="");

	//upload and description
	control = GetItem("demoapp");
	demo = control.value;
	if(demo!="x") {	//nothing selected
		EnableItem("uploadBtn", false);
		EnableItem("input", false);
		EnableItem("desc", false);
	}
	else {	//upload an input file
		EnableItem("uploadBtn", state!="busy");
		EnableItem("input", state!="busy");
		EnableItem("desc", state!="busy");
	}
}

function GetAppName(app)
{
	if(app=="x") {
		control = GetItem("input");
		return "Uploaded: " + control.value;
	}
	else if(app=="ToyProblem") {
		return "Demo: Toy Problem";
	}
	else if(app=="TravelRoutingProblem") {
		return "Demo: Travel Routing";
	}
	else if(app=="HIVSequences") {
		return "Demo: HIV Sequences";
	}
	else if(app=="digits") {
		return "Demo: Handwritten Digits from US Postal Service";
	}
	else if(app=="faceclustering") {
		return "Demo: Clustering Images Derived From Olivetti Face Database";
	}
	else if(app=="GeneFindingProblem") {
		return "Demo: Gene Finding";
	}
	return "Unknown application";
}


function ParseStatus(str)
{
	control = GetItem("timeMin");
	if(control) {
		today = new Date();
		diff = today.getTime() - startTime;
		mills = diff % 1000;
		sec = Math.floor(diff/1000);
		min = Math.floor(sec/60);
		hour = Math.floor(min/60);
		sec %= 60;
		min %= 60;
		time = "";
		if(hour > 0) {
			if(hour<10) {
				time = "0" + hour + ":";
			}
			else {
				time  += hour + ":";
			}
		}
		else {
			time = "00:";
		}
		if(min>0) {
			if(min<10) {
				time += "0" + min + ":";
			}
			else {
				time += min + ":";
			}
		}
		else {
			time += "00:";
		}
		if(sec>0) {
			if(sec<10) {
				time += "0" + sec;
			}
			else {
				time += sec;
			}
		}
		else {
			time += "00";
		}
/*
		time +=  ".";
		if(mills<10) {
			time += "00" + mills;
		}
		else if(mills<100) {
			time += "0" + mills;
		}
		else {
			time += mills;
		}
*/
//		control.value = diff;
		control.value = "Elapsed time: " + time;
	}
	var state = GetValue(str, "state");
	if(state=="timeout") {
		alert("Session timed out or the server restarted. This page will be reloaded.");
		location.reload(true);
		return;
	}
	EnableControls(state);
	setAjaxTimer = state=="busy";
	var msg = "";
	var status = GetValue(str, "status");
	if(status) {
		msg = msg + status;
	}
	var error = GetValue(str, "error");
	if(error) {
		msg = msg + error;
	}
	var instruct = GetValue(str, "instruct");
	if(instruct) {
		msg = msg + instruct;
	}
	if(msg!="") {
		control = GetItem("scrollContent");
		if(control) {
			control.innerHTML = results + "<br><br>" + msg;
			control.scrollTop = control.scrollHeight;
			control.scrollTop = control.scrollHeight;
			control.scrollTop = control.scrollHeight;
		}
		if(state=="done" || state=="idle") {
			//remove the instruction and the error message parts of the msg
			control = GetItem("demoapp");
			if(control) {
				appName = GetAppName(control.value);
			}
			else {
				appName = "Unknown Application";
			}
			msg = msg.replace("Click \"Start\" to run again or upload new input or choose a new demo application.", "=== " + appName + " ===<br><br>");;
			msg = msg.replace("\"green\"", "\"black\"");
			results += msg;
		}
	}
	var netsim = GetValue(str, "netsim");
//netsim = "<img border=0 src=\"http://www.psi.utoronto.ca/~weijun/images/netsim.png\">";
	if(netsim!=false) {
		control = GetItem("netsimContent");
		if(control) {
			control.innerHTML = netsim;
			control.scrollTop = control.scrollHeight;
			control.scrollTop = control.scrollHeight;
			control.scrollTop = control.scrollHeight;
		}
	}
	var downloadURL = GetValue(str, "downloadURL");
	if(downloadURL!=false) {
		control = GetItem("result");
		if(control) {
			control.value = downloadURL;
		}
	}
	var plotURL = GetValue(str, "plotURL");
	var userLoad = GetValue(str, "userLoad");
	if(plotURL!=false) {
		control = GetItem("plotURL");
		if(control) {
			control.value = plotURL;
			EnableItem("plotBtn", true);
		}
		timerCounter++;
		if(timerCounter>=timerCount || timerCounter==1) {
			control = GetItem("userLoad");
			if(control) {
				control.value = userLoad;
			}
		}
		if(timerCounter>=timerCount || state!="busy") {
			control = GetItem("netsimThumbnail");
			if(control) {
				today = new Date();
				control.innerHTML = "<a href=\"javascript:plot();\" border=\"0\"><img src=\"" + plotURL + "&tm=" + today.getTime() + "&t=thumbnail\" width=168 height=125 alt=\"plot thumbnail\" border=\"0\"></a>";
			}
			timerCounter = 0;
		}
	}
	if(state!="busy") {
//			control = GetItem("userLoad");
//			if(control) {
//				control.value = "";
//			}
			control = GetItem("ani");
			if(control) {
				control.innerHTML = "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<img border=\"0\" src=\"stiAP.gif\"><br><br>";
			}
	}
}

function GetXmlHttpObject()
{
	var xmlHttp=null;
	try
	{
		// Firefox, Opera 8.0+, Safari
		xmlHttp=new XMLHttpRequest();
	}
	catch (e)
	{
		// Internet Explorer
		try
		{
			xmlHttp=new ActiveXObject("Msxml2.XMLHTTP");
		}
		catch (e)
		{
			xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");
		}
	}
	return xmlHttp;
}


function stateChanged() 
{ 
	if (xmlHttp.readyState==4)
	{ 
		ParseStatus(xmlHttp.responseText);
		if(setAjaxTimer) {
			timerAjax = setTimeout("timerHandler()", timerInterval);
		}
	}
}



function getStatus()
{
	xmlHttp = GetXmlHttpObject();
	if (xmlHttp==null)
	{
		alert ("Your browser does not support AJAX!");
		return;
	} 
	var url="getStatus.php";
	var postData = "wtd=" + wtd;
	var pref, prefCheck;
	if(wtd=="start") {
		control = GetItem("maxits");
		postData += "&maxits=" + escape(control.value);
		control = GetItem("convits");
		postData += "&convits=" + escape(control.value);
		control = GetItem("dampfact");
		postData += "&dampfact=" + escape(control.value);
		control = GetItem("pref");
		pref = control.value;
		prefCheck = "useFile";
		control = GetItems("prefCheck");
		if(control.length) {
			if (control[1].checked) prefCheck = "usePref";
			else if (control[2].checked) {
				prefCheck = "useMedian";
				pref="median";
			}
		}
			
		if(prefCheck=="usePref" || prefCheck=="useMedian") {
			postData += "&overwritePref=" + "overwrite";
		}
		postData += "&pref=" + escape(pref);
		control = GetItem("desc");
		postData += "&desc=" + escape(control.value);
	}
	else if(wtd=="stop") {
	}
	else if(wtd=="status") {
	}
	else if(wtd=="demo") {
	}
	xmlHttp.onreadystatechange=stateChanged;
	xmlHttp.open("POST",url,true);
	xmlHttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
	xmlHttp.setRequestHeader("Content-length", postData.length);
	xmlHttp.setRequestHeader("Connection", "close");
	xmlHttp.send(postData);
}

function startApp()
{
	control = GetItem("netsimContent");
	if(control) control.innerHTML = "";
	control = GetItem("netsimThumbnail");
	if(control) control.innerHTML = "";
	control = GetItem("ani");
	if(control) control.innerHTML = "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<img border=\"0\" src=\"aniAP.gif\"><br><br>";
	today = new Date();
	startTime = today.getTime();
	wtd = "start";
	getStatus();
}

function stopApp()
{
	clearTimeout(timerAjax);
	timerAjax = null;
	wtd = "stop";
	getStatus();
}

function timerHandler()
{
	wtd = "status";
	getStatus();
}

function download()
{
	control = GetItem("result");
	if(control) {
		url = control.value;
		window1 = open(url, 'apDownload', 'width=100,height=20');
		window1.focus();
	}
	else {
		alert("Cannot get the download URL.");
	}
}

function downloadDemo()
{
	control = GetItem("demoapp");
	if(control) {
		url = window.location.href + "downloadDemoInput.php?d=" + control.value;
		window1 = open(url, 'apDownloadDemoData', 'width=100,height=20');
		window1.focus();
	}
	else {
		alert("Cannot get the download URL.");
	}
}

function plot()
{
	control = GetItem("plotURL");
	if(control) {
		url = control.value;
		var window1 = open(url, 'apPlot', 'width=680,height=680');
		window1.focus();
	}
	else {
		alert("Cannot get the plot URL.");
	}
}

function demoDesc(demo)
{
	if(demo=="ToyProblem") {
		return "Similarities for 25 two-dimensional data points were computed using negative Euclidean distance.";
	}
	else if(demo=="TravelRoutingProblem") {
		return "Similarities for 456 commercial airports were computed using negative estimated travel time between pairs of North American cities, including the effects of headwinds, stop-over delays, connection scheduling, etc.";
	}
	else if(demo=="GeneFindingProblem") {
		return "Similarities for 10,000 exon-resolution DNA probes were computed by taking into account the degree of co-expression across 12 tissues and proximity of the corresponding DNA segments in the genome. The set is sparse, because far-apart probes cannot belong to the same transcript or gene, so their similarities are not computed (set to -Inf).";
	}
	else if(demo=="digits") {
		return "Similarities for 2000 16x16 images of handwritten digits from Buffalo (provided by the US postal service) were computed using the negative sum of squared pixel differences between pairs of images.";
	}
	else if(demo=="faceclustering") {
		return "Similarities for 900 faces derived from the Olivetti face database were computed using the negative sum of squared pixel differences between pairs of images.";
	}
	else {
		return demo;
	}
}
