function eCallback() {
	/*PUBLIC*/
	this.ShowErrorsAtClient = true; /*For debugging*/
	this.ThrowExceptionsAtClient = true; /*For debugging*/
	this.method = "get"; /*"post","get"*/
	this.AddParam = this.eCallback_AddParam;
	this.ResetParams = this.eCallback_ResetParams;
	this.Post = this.eCallback_Post
	this.AbortAll = this.eCallback_AbortAll;
	this.timeout = 0; /*milliseconds to timeout, 0 no timeout*/
	this.bypassCache = true; /*keep no cache reload every time*/
	this.doubleEncodeURI = false; /*Double encoding (passing "α" as "%CE%B1") for utf-8 problems. */

	/*PRIVATE*/
	this.eCallback_pendingRequests = new Array();
	this.eCallback_arParams = new Array();		
	this.eCallback_ResetParams();
	this.eCallback_iTimeout = null;
}

eCallback.prototype.eCallback_InitPbx = function() {
	var eCallback_http = null;
	if(window.XMLHttpRequest) {
		try {
			eCallback_http = new XMLHttpRequest();
		}
		catch(e){}
	}
	else {
		/*Version 5 has bugs with greek characters*/
		var xhrVersion = [ "MSXML2.XMLHttp.7.0", "MSXML2.XMLHttp.6.0", "MSXML2.XMLHttp.4.0","MSXML2.XMLHttp.3.0","MSXML2.XMLHttp","Microsoft.XMLHttp" ];
		for (var i = 0; i < xhrVersion.length; i++) {
			try {
				eCallback_http = new ActiveXObject(xhrVersion[i]);
				break;
			} 
			catch(e){}
		}		
	}
	if(!eCallback_http) {
		/*@cc_on@*/
		/*@if(@_jscript_version>=5){
			try{
				eCallback_http=new ActiveXObject('msxml2.xmlhttp')
			}
			catch(e){
				try{
					eCallback_http=new ActiveXObject('Microsoft.XMLHTTP')
				}
				catch(e){}
			}
		}
		@else;
		eCallback_http=false;
		@end;@*/
	}
	return eCallback_http;
}
/*PRIVATE Called after each post/get*/
eCallback.prototype.eCallback_ResetParams = function() {
	this.eCallback_arParams = new Array();
}
/*PRIVATE Called to get params as string for post/get*/
eCallback.prototype.eCallback_GetParams = function() {
	var sParams = "";
	
	for (i=0;i<this.eCallback_arParams.length;i++){
	
		//var arParamValues=this.eCallback_arParams[i].split("=");		
		//if(this.doubleEncodeURI) arParamValues[1] = encodeURI(encodeURIComponent( arParamValues[1] ));
		//else					 arParamValues[1] = encodeURIComponent( arParamValues[1] );		
//		sParams += arParamValues[0]+"="+arParamValues[1];
		
		sParams += arParamValues=this.eCallback_arParams[i];
		if (i < this.eCallback_arParams.length-1)
			sParams +=  "&"				
	}
	var oDate=new Date();
	if (this.bypassCache){
		sParams += "&eCallback_bypassCache=dt" + oDate.valueOf();
	}
	
	return sParams;
}	
/*PUBLIC addparameters to send*/
eCallback.prototype.eCallback_AddParam = function(name, value) {
	if(this.doubleEncodeURI) value = encodeURI(encodeURIComponent( value ));
	else					 value = encodeURIComponent( value );

	this.eCallback_arParams.push( name+"="+value );
}
/*PUBLIC resetParams to send*/
eCallback.prototype.eCallback_ResetParams = function() {
	this.eCallback_arParams = new Array();
}
/*PUBLIC make the post*/
eCallback.prototype.eCallback_Post = function(s) {
	var eCallback_http = this.eCallback_InitPbx();
	if (s == ""){
		alert("Η σελίδα για την κλήση (πρώτη παράμετρος) δεν μπορεί να είναι κενή");
		return false;
	}
	if (this.timeout != 0){
		var oThis = this;
	    this.eCallback_iTimeout = window.setTimeout(oThis.eCallback_OnTimeout, this.timeout);
	}

	if(eCallback_http) {
		/*Add to pending requests*/
		var requestIndex = this.eCallback_pendingRequests.length;
		this.eCallback_pendingRequests[requestIndex] = new Array();
		this.eCallback_pendingRequests[requestIndex][0] = eCallback_http;
		this.eCallback_pendingRequests[requestIndex][1] = new Object();
		this.eCallback_pendingRequests[requestIndex][1].aborted = false;
		this.eCallback_pendingRequests[requestIndex][1].completed = false;
		/*Bind events*/
		var oThis = this;
		eCallback_http.onreadystatechange = function() {
			oThis.eCallback_ReadyStateChange(eCallback_http, requestIndex);
		}	
		/*Decide method and send*/
		if (this.method.toUpperCase() == "GET"){
			eCallback_http.open("GET", s+"?"+this.eCallback_GetParams(), !this.eCallback_isSynchronous());
		}
		else{
			eCallback_http.open("POST", s, !this.eCallback_isSynchronous());
			eCallback_http.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
		}
		this.eCallback_DoSend(eCallback_http);

		/*Reset*/
		this.eCallback_ResetParams();
		
		/*Handle sychronous*/
		if(this.eCallback_isSynchronous()) {
			try {
				return this.eCallback_GetResponse(eCallback_http, requestIndex);
			}
			catch(e) {
				this.eCallback_handleError(e, eCallback_http);
			}
		}
	}
}

/*START EVENTS*/
eCallback.prototype.OnBeforeInitialize = function(){};
eCallback.prototype.OnLoading = function(){};
eCallback.prototype.OnLoaded = function(){};
eCallback.prototype.OnInteractive = function(){};
eCallback.prototype.OnComplete = function(responseText){};/*Note function bellow!!!!!!!!!!!!!!!*/
	eCallback.prototype.eCallback_isSynchronous = function(){return (this.OnComplete.toString().replace(/\n+/gi, '').replace(/\s+/gi, '') == "function(responseText){}")};
eCallback.prototype.OnAbort = function(){};
eCallback.prototype.OnError = function(status, statusText){};

/*PRIVATE onTimeout handling*/
eCallback.prototype.eCallback_OnTimeout = function(){
	this.AbortAll();
	this.OnLoading();
};

/*PRIVATE check state*/
eCallback.prototype.eCallback_ReadyStateChange = function(eCallback_http, requestIndex){

	this.eCallback_handleWaitMsg(eCallback_http.readyState);
	
	switch (eCallback_http.readyState) {
		case 0:
			this.OnBeforeInitialize();
			break;
	    case 1 :
			this.OnLoading();
	        break;
	    case 2 :
			this.OnLoaded();
			break;
	    case 3 :
			this.OnInteractive();
	        break;
	    case 4 :
			if( eCallback_http.status == 0 ){
				if (this.OnAbort) this.OnAbort();
			}
			else if( eCallback_http.status == 200 && eCallback_http.statusText == "OK" ){
				if(this.eCallback_isSynchronous()) return;
				try {
					var result = this.eCallback_GetResponse(eCallback_http, requestIndex);
					if(this.eCallback_pendingRequests[requestIndex][1].aborted) return;
					this.OnComplete(result);
				}
				catch (e) {
					this.eCallback_handleError(e, eCallback_http);
				}	
			}
			else{
				var eCallback_pb_ex = new Error("Κατά την κλήση επιστράφηκε το εξής λάθος: " + eCallback_http.status + " - " + eCallback_http.statusText);
				eCallback_pb_ex.responseText = eCallback_http.responseText;
				eCallback_pb_ex.name = "PostbackError";
				this.eCallback_handleError(eCallback_pb_ex, eCallback_http);
			}
	        break;
		default:
			this.OnError(eCallback_http.status, eCallback_http.statusText, eCallback_http.responseText);
	}
}
/*END EVENTS*/

/*PRIVATE process response*/
eCallback.prototype.eCallback_GetResponse = function(eCallback_http, requestIndex) {
/*	for(var i = 0; i < this.eCallback_pendingRequests.length; i++) {
		if(this.eCallback_pendingRequests[i] == eCallback_http) {
			this.eCallback_pendingRequests.splice(requestIndex, 1);		
			break;
		}
	}
*/
	if(this.eCallback_pendingRequests[requestIndex][1].aborted) return false;
	
	this.eCallback_pendingRequests[requestIndex][1].completed = true;
	
	if (eCallback_http.status == 200) {
		var response = eCallback_http.responseText;
		if(eCallback_http.responseXML != null) {
			var d = eCallback_http.responseXML.documentElement;
			if(d != null) {
				if(d.nodeName != 'pbext'){
					response = eCallback_http.responseText;
				}
				else {
					window.eval(d.firstChild.firstChild.nodeValue);
					response = d.lastChild.firstChild.nodeValue;
				}
			}
		}
		
		if (response.indexOf("eCallback_forceReload") > -1 || response.indexOf("epsilonWeb_errorCode") > -1){
			if ( response.indexOf("epsilonWeb_errorCode") > -1 ) {
				i =  response.indexOf("epsilonWeb_errorCode");
				epsilonWeb_errorCode = response.substr(i+21, 3);
			}
			if ( window.location.toString().indexOf("?") > -1 ){				
				window.location = parent.location + "&epsilonWeb_errorCode=" + epsilonWeb_errorCode;
			}
			else{
				window.location = parent.location + "?epsilonWeb_errorCode=" + epsilonWeb_errorCode;
			}

			return false;			
		}
		else{
			return response;
		}
	}
	else {
		var eCallback_pb_ex = new Error("Κατά την κλήση επιστράφηκε το εξής λάθος: " + eCallback_http.status + " - " + eCallback_http.statusText);
		eCallback_pb_ex.responseText = eCallback_http.responseText;
		eCallback_pb_ex.name = "PostbackError";
		this.eCallback_handleError(eCallback_pb_ex, null);			
	}
}
/*PRIVATE send data*/
eCallback.prototype.eCallback_DoSend = function(eCallback_http) {
	try{
		if (this.method == "get"){
			try{
				eCallback_http.send(null);
			}
			catch(e){/*hack to catch the error of the error (smart ie)*/
			}
		}
		else{
			try{
				eCallback_http.send(this.eCallback_GetParams());
			}
			catch(e){/*hack to catch the error of the error (smart ie)*/
			}				
		}
	}
	catch(e){
		this.eCallback_handleError(e, eCallback_http);
	}
	
}	
/*PRIVATE abort requests*/
eCallback.prototype.eCallback_AbortAll = function() {
    try{
        window.clearTimeout(this.eCallback_iTimeout);
    }
    catch(e){
		this.eCallback_handleError(e, null);
    }

	for(var i = 0; i < this.eCallback_pendingRequests.length; i++) {
		try {
			this.eCallback_pendingRequests[i][1].aborted = true;
			this.eCallback_pendingRequests[i][0].onreadystatechange = function() {};
			this.eCallback_pendingRequests[i][0].abort();
		}
		catch(e) {
			this.eCallback_handleError(e, null);
		}
	}
}

/*PRIVATE handle errors*/
eCallback.prototype.eCallback_handleError = function(e, eCallback_http){
	if (eCallback_http){
		if ( (this.ShowErrorsAtClient || this.ThrowExceptionsAtClient) && eCallback_http.readyState == 4){
			if(this.OnComplete) this.OnComplete(eCallback_http.responseText, e);
		}
	}
	if (this.ShowErrorsAtClient){
		
		if(e.name.toLowerCase() == "postbackerror" && e.responseText.length > 0) {
			if (window.confirm(e.name + ": " + e.message + "\r\n\r\nΘέλετε να δείτε την σελίδα που επιστράφηκε;")) {
				var errorWin = window.open("", "eCallback_errorWindow", "menubar=1,resizable=1,width=600,height=400");
				errorWin.document.open();
				errorWin.document.write(e.responseText);
				errorWin.document.close();
				errorWin.focus();
			}
		}
		else {
			if (!this.ThrowExceptionsAtClient){
				alert(e.name + "\n" + e.message);
			}
			else{
				throw e;
			}
		}
	}
}

/*PRIVATE handle messages*/
eCallback.prototype.eCallback_handleWaitMsg = function (i){
	if(!this.eCallback_isSynchronous())	return;
	switch (i) {
		case 0:
			window.status = "Παρακαλώ περιμένετε... ";
			break;
	    case 1 :
			window.status = "Παρακαλώ περιμένετε... ";
	        break;
	    case 2 :
			window.status = "Παρακαλώ περιμένετε... ";
			break;
	    case 3 :
			window.status = "Παρακαλώ περιμένετε... ";
	        break;
	    case 4 :
			window.status = "";
			break;
		default:
			window.status = "";
			break;
	}
}
