var WSHandler = function(event) {
	// console.log(event);
	data = event.data;
	// console.log("   -->" + data);
	try {
		var obj = JSON.parse(data);
		switch (obj.action) {
		case 'ping':
		case 'poing':
			break;
		case 'onExecuteResult':
			onExecuteResult(obj);
			break;
		case 'onListContractProcess':
			onListContractProcess(obj);
			break;
		case 'onStartContract':
			onStartContract(obj);
			break;
		case 'onKillContractProcess':
			logComm(obj);
			break;
		case 'onKillAllContract':
			onKillAllContract(obj);
			break;
		case 'onOutputStream':
			displayOutput(obj);
			break;
		case 'onSaveFile':
			onSaveFile(obj);
			break;
		case 'uploadNext':
			onUploadNext(obj);
			break;
		case 'sendNextSegment':
			global.wssocket.sendNextSegment();
			break;
		case 'sendSeg':
			receiveSeg(obj);
			break;
		case 'onException':
			logException(obj);
			break;
		case 'onHashResult':
			onHashResult(obj);
			break;
		case 'onDumpContract':
			onDumpContract(obj);
			break;
		default:
			displayOutput(obj);
			break;
		}
	} catch (err) {
		console.log(err);
	}
};
var logException = function(obj) {
	global.tempobj = obj;
	$("#responseStatus").html("Exception (" + obj.executeTime + "ms)");
	displayOutput(obj);
};

var logComm = function(obj) {
	console.log(obj);
};
var displayOutput = function(obj) {
	displayOutputStr(obj.data);
};

var displayOutputStr = function(str) {
	console.log("[cm.js] displayOutput:" + str);
};
var getControlWsUrl = function(host) {
	var prefix = "ws://";
	if (document.location.href.startsWith("https"))
		prefix = "wss://";
	var path = document.location.pathname.lastIndexOf("/");
	path = document.location.pathname.substr(0, path + 1);
	path += "SCExecutor";
	return prefix + host + path;
};
var initWSocket = function() {
	var host = getHost();
	var url = getControlWsUrl(host);
	global.wssocket = createWssocket(url, function() {
		listContractProcess();
	}, WSHandler);
};
// ====== wsHandler
var onStartContract = function(obj) {
	// console.log(obj);
	var result = JSON.parse(obj.data);

	$("#responseStatus").html(result.status + "  (" + obj.executeTime + "ms)");
	global.responseEditor.setValue(result.result);
	// $("#tabdiv").editableSelect('add', obj.cid);
	// $("#tabdiv").editableSelect()[0].value = obj.cid;
};
var onExecuteResult = function(obj) {
	// console.log(obj);
	var data = JSON.parse(obj.data);
	$("#responseStatus").html(data.status + "  (" + obj.executeTime + "ms)");
	global.responseEditor.setValue(data.result);
	// console.log(data);
	var totalLines = global.responseEditor.lineCount();
	global.responseEditor.autoFormatRange({
		line : 0,
		ch : 0
	}, {
		line : totalLines
	});
	if (data.analysis != undefined && data.analysis.length > 0) {
		// displayOutputStr(data.analysis);
	}
};
var onListContractProcess = function(obj) {
	var data = JSON.parse(obj.data);
	global.contracts = data;
	var html = "";

	// $("#tabdiv").html("");
	global.contractName2ID = {};
	for (var i = 0; i < data.length; i++) {
		global.contractName2ID[data[i].name] = data[i].id;
		html += "<li class=\"ui-widget-content\">" + data[i].name + "</li>";
		// $("#tabdiv").append(
		// $("<option></option>").attr("value", data[i].id).text(
		// data[i].id));
	}
	$("#contractList").html(html);
	$("#contractList").selectable(
			{
				stop : function() {
					var result = "";
					global.selectedContracts = [];
					global.selectedContractIndexs = [];

					$(".ui-selected", this).each(function() {
						var index = $("#contractList li").index(this);
						global.selectedContracts.push(this.innerText);
						global.selectedContractIndexs.push(index);
					});
				// 	console.log("[cm.js] selectContractResult:"
				// 			+ global.selectedContracts);
				}
			});
	// $("#tabdiv").selectmenu("refresh");
	// $("#tabdiv").html(html);
	// $("yourid/class here").append($("<option></option>").attr("value",
	// youroption-value).text(youroption-text));

};
var onSaveFile = function(obj) {
	alert("Save file:" + obj.data);
};
var onKillAllContract = function(obj) {
	customAlert(obj.data);
};
var onHashResult = function(obj) {
	$("#hashResult").html("刚刚操作的数链指纹:" + obj.data);
};
var onDumpContract = function(obj) {
	// console.log("DumpResult:" + obj.data);
	if (obj.data == "success") {
		listDumpMemoryDir();
	}
};
// ====== wsHandler done!
var switchContract = function(off) {
	// var contract = global.contracts[off];
	// global.scriptEditor.setValue(contract.script);
	// $("#tabdiv")[0].value = contract.id;
	var pingObj = {};
	pingObj.action = "connectTo";

	pingObj.name = $("#tabdiv")[0].value;
	pingObj.id = global.contractName2ID[pingObj.name];
	global.wssocket.send(JSON.stringify(pingObj));
}
var countChar = function(str, c) {
	var ret = 0;
	for (var i = 0; i < str.length; i++) {
		if (str.charAt(i) == c)
			ret++;
	}
	return ret;
}
var generate = function() {
	$.ajax({
		url : "./SCManager?action=generatePrivateKey",
		dataType : "json"
	}).done(function(result) {
		if (result.status) {
			localStorage.setItem("PrivKey", result.data);
			alert("Key successfully generated!");
			initRest();
		}
	});
}

var initGlobal = function() {
	window.global = {};
	global.privKey = localStorage.getItem("PrivKey");
	if (global.privKey == undefined || global.privKey == null
			|| global.privKey.length < 100) {
		generate();
	} else
		initRest();

}
var setMainHost = function() {
	var mainHost = $("#targetHost")[0].value;
	localStorage.setItem("mainHost", mainHost);
}
var initRest = function() {
	var mainHost = localStorage.getItem("mainHost");
	if (mainHost == undefined) {
		localStorage.setItem("mainHost", "39.106.6.6:8080");
		mainHost = localStorage.getItem("mainHost");
	}
	$("#targetHost")[0].value = mainHost;
};
var onUploadNext = function() {
	var request = {};
	request.action = "startContract";
	request.owner = global.privKey;
	request.isPartial = false;
	request.script = global.toSend;
	if (request.script.length > 1024) {
		global.toSend = request.script.substr(1024);
		request.script = request.script.substr(0, 1024);
		request.isPartial = true;
	} else {
		global.toSend = "";
	}
	// console.log("Upload nextPart:");
	// console.log(JSON.stringify(request));
	global.wssocket.send(JSON.stringify(request));
};
var disposeContract = function(request, host, contractIndex) {
	// fileWs.send(JSON.stringify(request));
	// console.log("[cm.js] disposeContract:" + host + "-->"
	// 		+ JSON.stringify(request));
	var wsUrl = getFileWsUrl(host);
	var fileWs = new WebSocket(wsUrl);
	fileWs.onerror = function(error) {
		console.log(error);
	};
	fileWs.contractIndex = contractIndex;
	fileWs.onopen = function(error) {
		fileWs.send(JSON.stringify(request));
	};
	fileWs.currHost = host;
	fileWs.zipInfo = request;
	fileWs.onmessage = downloadHandler;
}
var updateProgress = function(progressIndex, host, progress) {
	if (isNaN(progress)) {
		console.log("StopHere");
	}
	var hostMap = global.progressStat.get(progressIndex);
	hostMap.set(host, progress);
	var total = 0;
	for (var j = 0; j < global.hosts.length; j++) {
		total += hostMap.get(global.hosts[j]);
	}
	// console.log("[cm.js] updateProgress:" + total);
	$($("#progressBars .progressDiv")[progressIndex]).progressbar({
		value : Math.floor(total / global.hosts.length)
	});
};


var downloadHandler = function(obj, wssocket) {
	data = event.data;
	// console.log("   -->" + data);
	try {
		var obj = JSON.parse(data);
		switch (obj.action) {
		case "onDownloadContract":
			// console.log(JSON.stringify(obj));
			updateProgress(this.contractIndex, this.currHost,
					obj.executeTime * 0.95);
			//console.log("[cm.js] obj.executeTime = " + obj.executeTime * 0.95 + " ; " + obj.executeTime);
			if (obj.data == "success") {
				console.log("[cm.js] downloadHandler successs");
				startContractWithHost(this.currHost, this.zipInfo.fileName,
						this.contractIndex);
				this.close();
			}
			break;
		case "onStartContract":
			updateProgress(wssocket.contractIndex, wssocket.currHost, 100);
			wssocket.close();
			break;
		default:
		}
	} catch (err) {
		console.log(err);
	}
}
var getControlWsUrl = function(host) {
	var prefix = "ws://";
	if (document.location.href.startsWith("https"))
		prefix = "wss://";
	var path = document.location.pathname.lastIndexOf("/");
	path = document.location.pathname.substr(0, path + 1);
	path += "SCExecutor";
	return prefix + host + path;
};
var startContractWithHost = function(host, fileName, contractIndex) {
	
	//console.log("[cm.js] host = " + host + " ; fileName" + fileName + " ; contractIndex = " + contractIndex);
	var wsUrl = getControlWsUrl(host);
	//console.log("[cm.js] this = " + this);
	var controller = createWssocket(wsUrl, function() {
		// onopen;
		var request = {};
		request.action = "startContractInTempZips";
		request.owner = global.privKey;
		request.path = fileName;
		request.script = "empty";
		controller.send(JSON.stringify(request));
		this.contractIndex = contractIndex;
		this.currHost = host;
	}, downloadHandler);

};

var startContract = function() {
	
	global.progressStat = new Map();
	for (var i = 0; i < global.selectedProjects.length; i++) {
		var map = new Map();
		for (var j = 0; j < global.hosts.length; j++) {
			map.set(global.hosts[j], 0);
		}
		global.progressStat.set(global.selectedProjectIndexs[i], map);
	}

	for (var i = 0; i < global.selectedProjects.length; i++)
		for (var j = 0; j < global.hosts.length; j++) {
			var request = {};
			request.action = "downloadContract";
			request.mainHost = $("#targetHost")[0].value;  
			request.projectName = global.selectedProjects[i].replace(" ", "");
			request.fileName = request.projectName + "_" + new Date().getTime()
					+ ".ypk";
			
			disposeContract(request, global.hosts[j],
					global.selectedProjectIndexs[i]);
		}

};
var dumpContract = function() {
	var pingObj = {};
	for (var i = 0; i < global.selectedContracts.length; i++) {
		pingObj.action = "dumpContract";
		pingObj.target = "/memoryDumps/" + global.selectedContracts[i] + "_"
				+ new Date().getTime() + ".dyjs";
		pingObj.contractID = global.selectedContracts[i];
		//console.log("[cm.js] pingObj.target = " + pingObj.target);
		//console.log("[cm.js] pingObj.contractID = " + pingObj.contractID);
		
		global.wssocket.send(JSON.stringify(pingObj));
	}
};

var loadMemory = function() {
	var pingObj = {};
	for (var i = 0; i < global.selectedContracts.length; i++) {
		pingObj.action = "loadMemory";
		pingObj.target = "/memoryDumps/" + global.selectedDumps[0];
		pingObj.contractID = global.selectedContracts[i];
		global.wssocket.send(JSON.stringify(pingObj));
	}
};

var executeContractWithDynamicResult = function() {
	var request = {};
	request.action = "executeContract";
	request.requestID = new Date().getTime() + "";
	request.contractID = $("#tabdiv")[0].value;
	request.arg = global.argEditor.getValue();
	request.privKey = global.privKey;
	request.withDyanmicAnalysis = true;
	localStorage.setItem("persisArg", JSON.stringify(request));
	global.wssocket.send(JSON.stringify(request));
};
var executeContract = function() {
	var request = {};
	request.action = "executeContract";
	request.requestID = new Date().getTime() + "";
	request.contractID = $("#tabdiv")[0].value;
	request.arg = global.argEditor.getValue();
	request.privKey = global.privKey;
	localStorage.setItem("persisArg", JSON.stringify(request));
	global.wssocket.send(JSON.stringify(request));
};
var listContractProcess = function() {
	var request = {};
	request.action = "listContractProcess";
	global.wssocket.send(JSON.stringify(request));
};

var killContractProcess = function() {
	var request = {};
	request.action = "killContractProcess";
	request.requestID = new Date().getTime() + "";
	request.name = $("#tabdiv")[0].value;
	request.id = global.contractName2ID[request.name];
	global.wssocket.send(JSON.stringify(request));
};
var staticVerify = function() {
	var request = {};
	request.action = "staticVerifyContract";
	// TODO should be pubkey
	request.owner = global.privKey;
	request.isPartial = false;
	// TODO ignore contractid
	request.contractid = $("#tabdiv")[0].value;
	request.script = global.scriptEditor.getValue();
	request.path = $(".ui-tabs-active").find("a").html();
	localStorage.setItem("persisStatus", JSON.stringify(request));
	if (request.path.startsWith("/"))
		request.script = "empty";
	/*
	 * if (request.script.length > 1024) { global.toSend =
	 * request.script.substr(1024); request.script = request.script.substr(0,
	 * 1024); request.isPartial = true; }
	 */
	global.wssocket.send(JSON.stringify(request));
};
var downloadContract = function() {
	if (global.lastClickedProjectId == undefined)
		global.lastClickedProjectId = 0;
	var projectName = global.projects[global.lastClickedProjectId];
	var url = window.location.href.replace("/scide.html",
			"/downLoadServlet?projectName=");
	url += projectName;
	window.open(url);

};
var killAllContract = function() {
	var request = {};
	request.action = "killAllContract";
	global.wssocket.send(JSON.stringify(request));
};

var customAlert = function(message, title) {
	if (!title)
		title = 'Alert';

	if (!message)
		message = 'No Message to Display.';

	$('<div></div>').html(message).dialog({
		title : title,
		resizable : false,
		modal : true,
		buttons : {
			'Ok' : function() {
				$(this).dialog('close');
			}
		}
	});
}
var init = function() {
	initGlobal();
	initWSocket();
	global.hosts = [];
	$("#serverList").selectable({
		stop : function() {
			var result = "";
			global.hosts = [];
			$(".ui-selected", this).each(function() {
				var index = $("#serverList li").index(this);
				global.hosts.push(this.innerText);
			});
			// console.log("[cm.js] selectResult:" + global.hosts);
		}
	});
};
var getRequestParameters = function() {
	var arr = (location.search || "").replace(/^\?/, '').split("&");
	var params = {};
	for (var i = 0; i < arr.length; i++) {
		var data = arr[i].split("=");
		if (data.length == 2) {
			params[data[0]] = data[1];
		}
	}
	return params;
};

var initHello = function() {
	var param = getRequestParameters();
	var type = parseInt(param["type"]);
	var template;
	switch (type) {
	case 1:
		template = getTemplate1(param["name"], decodeURI(param["list"]),
				param["expiredDate"]);
		break;
	case 2:
		template = getTemplate2(param["name"], decodeURI(param["list"]),
				param["expiredDate"]);
		break;
	case 3:
		var contractID = param["contractID"];
		$.ajax({
			url : "./SCManager?action=getCodeByID&contractID=" + contractID,
			dataType : "json"
		}).done(function(result) {
			global.fileContentMap.set(contractID, result.data);
			addTab({
				"title" : contractID
			});

		});
		return;
	default:
		return;
	}
	global.scriptEditor.setValue(template);
};