/**
* Ajax Controller Class
* Author: Vic
*/

function AjaxController() {
	if (window.XMLHttpRequest) {
	        this.XMLHttpRequestObject = new XMLHttpRequest();
	}
	else if (window.ActiveXObject) {
	        this.XMLHttpRequestObject = new ActiveXObject("Microsoft.XMLHTTP");
	}
	this.clearAll();
}
AjaxController.prototype.XMLHttpRequestObject = false;

/**
* Ready State Object Constatnts
*/
AjaxController.READY_STATE_UNINITIALIZED  	= 0;
AjaxController.READY_STATE_LOADING        	= 1;
AjaxController.READY_STATE_LOADED         	= 2;
AjaxController.READY_STATE_INTERACTIVE    	= 3;
AjaxController.READY_STATE_COMPLETE       	= 4;

/**
* HTTP Status Constants
*/
AjaxController.HTTP_STATUS_OK             	= 200; 
AjaxController.HTTP_STATUS_FOUND          	= 302;  

/**
*	Set AJAX Request Method  (default POST)
*/
AjaxController.prototype.setMethod = function(method) {
	switch(method.toLowerCase()) {
		case 'get':
			this._method = "GET";
			break;
		case 'post':
		default:
			this._method = "POST";
			break;
	}
}

/**
*	Set server address
*/
AjaxController.prototype.setServerUrl = function(serverUrl) {
	this._serverUrl = serverUrl;
}
/**
*	Get server address
*/
AjaxController.prototype.getRemoteUrl = function() {
	return this._serverUrl;
}

/**
* Set all parameters to default
*
*/
AjaxController.prototype.clearAll = function() {
	this._callback_func_user = new Array();
	this._object_handler = new Object();
	this._method = "POST";
	this._parameters = new Object();
	this._parameterCount = 0;
	this._serverClass = '';
	this._serverFunc = '';
	this._return_handler = '';
}

/**
* Setting On Ready State Change event handler
*
* @return  integer
*/ 
AjaxController.prototype.onReadyState = function() {
	if (this.XMLHttpRequestObject.readyState == AjaxController.READY_STATE_COMPLETE) {
		if(this.XMLHttpRequestObject.status == AjaxController.HTTP_STATUS_OK) {
    		this.hideLoader();
    		this._callback_func(this.XMLHttpRequestObject);
    	}
    	else {
    		AjaxController.showError('Error with request');	
    	}	
    }
}



/**
*	Set callback function (replacing default callback function)
*
* @param function callback_function
*	@return boolean is_success 
*/
AjaxController.prototype.setCallback = function(callback_func) {
		if (typeof(callback_func) != 'function')
    {
				return false;
		}
		this._callback_func = callback_func;
		return true;
}

/**
*	Add User Function To List of callback function
*
* @param function callback_function
*	@return boolean is_success 
*/
AjaxController.prototype.addCallback = function(callback_func) {
		if (typeof(callback_func) != 'function')
    {
				return false;
		}
		this._callback_func_user.push(callback_func);
		return true;
}

/**
*	Set handler for Response Object
*
*	@param 	string 		object_name
*	@param 	function 	handler
*	@return boolean is_success 
*/
AjaxController.prototype.setObjectHandler = function(extObject, callback_func) {
	
		if(typeof(extObject) != 'object') {
				return false;
		}
		if (typeof(extObject.getName) != 'function')
    	{
    		return false;
    	}
		objName = extObject.getName();
		if(typeof(objName) != 'string') {
				return false;
		}
			
		
		if (typeof(callback_func) == 'function')
    	{
    		this._object_handler[objName] = callback_func;
		}
		else {
			if(typeof(extObject.procObject) != 'function') {
    			return false;
    		}
    		this._object_handler[objName] = extObject.procObject;
		}
		
		
		return true;
}

/**
*	Set handler for return value
*
*/
AjaxController.prototype.setReturnHandler = function(return_handler) {
		if (typeof(return_handler) != 'function')
    	{
			return false;
		}
		this._return_handler = return_handler;
		return true;
}

/**
* Parameters Pair Class
*
* @param   string name
* @param   string value
* @return  void
*/
AjaxController.ParametersPair = function(name, value)
{
      this.name   = name;
      this.value  = value;
}

/**
* Added Parameters Pair to the Current Instanse of Object
*
* @param   string name
* @param   string value
* @return  void
*/ 
AjaxController.prototype.addParam = function(name, value) {
	this._parameters[this._parameterCount] = new AjaxController.ParametersPair(name, value);
	this._parameterCount++;
}

/**
*	Set Server Handler - function that will be called on server side
*
*	@param	string	class_name
*	@param	string	func_name
*	@return void
*/


/**
*	Add form values to request parameters
*
*/
AjaxController.prototype.addForm = function(form) {
	var elem, val;
	for (var i = 0; i < form.length; i++) {
		elem = form[i];
		if(elem.name == '') {
			continue;
		}
		switch (elem.type) {
			case "password":
			case "hidden":
			case "text":
			case "textarea":
				this.addParam(elem.name, elem.value);
				break;
			case "select-one":
				this.addParam(elem.name, elem[elem.selectedIndex].value );
				break;
			case "checkbox":
				if(elem.checked) {
					if(elem.value == '') {
						elem.value = 'on';
					}
					this.addParam(elem.name, elem.value);
				}
				break;
			case "radio":
				if(elem.checked) {
					if(elem.value == '') {
						elem.value = 'on';
					}
					this.addParam(elem.name, elem.value);
				}
				break;
		}
	}
	
	
}

AjaxController.prototype.setServerHandle = function(className, funcName) {
	this._serverClass = className;
	this._serverFunc = funcName;
}

/**
* Ajax Request Execute method
*
* @return  void
*/ 
AjaxController.prototype.execute = function() {
	var currentObj = this;
	if(this.XMLHttpRequestObject) {

	      requestData = '';
	      var requestDataArray = new Array(); 
	      for (var i = 0; i < this._parameterCount; i++)
          {
                var tmpString = new String(this._parameters[i].value);
                if ((tmpString.indexOf('&') != -1) || (tmpString.indexOf('+') != -1))
                {
                    this._parameters[i].value = encodeURIComponent(tmpString);
                }
				requestDataArray.push(this._parameters[i].name + '=' + this._parameters[i].value); 
          } 
          if(this._serverFunc != '') {
          		if(this._serverClass != '') {
          			requestDataArray.push('callUserClass='+this._serverClass);	
          		}
          		requestDataArray.push('callUserFunc='+this._serverFunc);
          }
          requestData = requestDataArray.join('&');
	      
	      this.XMLHttpRequestObject.onreadystatechange = function() {
	      	currentObj.onReadyState();
	      }
	      
          if(this._method == "GET") {
          		this.XMLHttpRequestObject.open(this._method, this._serverUrl + '?' + requestData, true);
          		this.XMLHttpRequestObject.overrideMimeType("text/xml");
          		this.XMLHttpRequestObject.send(null);
          }
          if(this._method == "POST") {
          		this.XMLHttpRequestObject.open(this._method, this._serverUrl, true);
          		this.XMLHttpRequestObject.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
          		this.XMLHttpRequestObject.send(requestData);
          }
          AjaxController.hideMessage();
          AjaxController.hideError();
          this.showLoader();
    }
}

/**
*	Decode JSON String
*
*	@param string	json_string
*/
AjaxController.decode = function(json){
	return eval('(' + json + ')');
}


/**
*	Skin Object
*
*/
AjaxController.skin = new Object();
AjaxController.skin.loader = "Loading...";

AjaxController.skin.message_window = new Object();
AjaxController.skin.message_window.start_tag 		= "<table>";
AjaxController.skin.message_window.mess_start_tag 	= "<tr><td>";
AjaxController.skin.message_window.mess_end_tag 	= "</td></tr>";
AjaxController.skin.message_window.end_tag 			= "</table>";

AjaxController.skin.error_window = new Object();
AjaxController.skin.error_window.start_tag 		= "";
AjaxController.skin.error_window.err_start_tag 	= "";
AjaxController.skin.error_window.err_end_tag 	= "<br />";
AjaxController.skin.error_window.end_tag 		= "";

/**
*	Show 'Loading' screen
*/
AjaxController.prototype.showLoader = function () {
	var loader = null;
	if((loader = document.getElementById('ajax-loader')) == null) {
		loader = document.createElement('div');
		loader.setAttribute('id', 'ajax-loader');
		loader.innerHTML = AjaxController.skin.loader;
		var body = document.getElementsByTagName('body')[0];
		body.appendChild(loader);
	}
	loader.style.display = 'inline';
		 
}
/**
*	Hide 'Loading' screen
*/
AjaxController.prototype.hideLoader = function () {
	if((loader = document.getElementById('ajax-loader')) != null) {
		loader.style.display = 'none';
	}
}

/**
*	Show 'Error' screen
*/
AjaxController.showError = function(text) {
	var error_div = null;
	if((error_div = document.getElementById('ajax-error')) == null) {
		error_div = document.createElement('div');
		error_div.setAttribute('id', 'ajax-error');
		var body = document.getElementsByTagName('body')[0];
		body.appendChild(error_div);
	}
	error_div.innerHTML = text;
	error_div.style.display = 'inline';	
}
/**
*	Hide 'Error' screen
*/
AjaxController.hideError = function(){
	if((error_div = document.getElementById('ajax-error')) != null) {
		error_div.style.display = 'none';
	}
}

/**
*	Show 'Message' screen
*/
AjaxController.showMessage = function(text) {
	var mess_div = null;
	if((mess_div = document.getElementById('ajax-message')) == null) {
		mess_div = document.createElement('div');
		mess_div.setAttribute('id', 'ajax-message');
		var body = document.getElementsByTagName('body')[0];
		body.appendChild(mess_div);
	}
	mess_div.innerHTML = text;
	mess_div.style.display = 'inline';	
}
/**
*	Hide 'Message' screen
*/
AjaxController.hideMessage = function(){
	if((mess_div = document.getElementById('ajax-message')) != null) {
		mess_div.style.display = 'none';
	}
}


/**
*	Function For Proccessing Error Messages From server
*
*	@param object	ErrorObject
*/
AjaxController.procErrors = function(object) {
	if(object.length == 0) {
    	AjaxController.hideError();
    	return false;
    }
    err_text = AjaxController.skin.error_window.start_tag;
    for(k=0; k<object.length; k++) {
    	if(typeof(object[k].Text) != 'undefined') {
    		err_text += AjaxController.skin.error_window.err_start_tag;
        	err_text += object[k].Text;
        	err_text += AjaxController.skin.error_window.err_end_tag;
        }
    }
    err_text += AjaxController.skin.error_window.end_tag;
    AjaxController.showError(err_text);
    return true;
}

/**
*	Function For Proccessing Messages From server
*
*	@param object	MessageObject
*/
AjaxController.procMessages = function(object) {

	if(object.length == 0) {
		AjaxController.hideMessage();
    	return false;
    }

	mess_text = AjaxController.skin.message_window.start_tag;
    for(k=0; k<object.length; k++) {
    	if(typeof(object[k].Text) != 'undefined') {
        	mess_text += AjaxController.skin.message_window.mess_start_tag;
        	mess_text += object[k].Text;
        	mess_text += AjaxController.skin.message_window.mess_end_tag;
        }
    }
    mess_text += AjaxController.skin.message_window.end_tag;
    AjaxController.showMessage(mess_text);
    return true;
}



/**
*	Default Callback Function
*	
*	@param string json_string
*
*/
AjaxController.prototype._callback_func = function(ReqObg) {
	var is_json_obj = true;
	
	try {
		var resObj = AjaxController.decode(decodeURI(ReqObg.responseText));
	}
	catch(eDecodeError) {
		is_json_obj = false;
		//AjaxController.showError("Error on Server Side: "+ReqObg.responseText);
	}
    
    if(is_json_obj) {
	    for(objName in resObj) {
	    	/*if(typeof(resObj[objName]) != 'object') {
	    		continue;
	    	}*/
	    	obj = resObj[objName];
	        switch(objName) {
	        	case 'Ajax-Error':
	        		AjaxController.procErrors(obj);
	        		break;
	        	case 'Ajax-Message':
	        		AjaxController.procMessages(obj);
	        		break;
	        	case 'Ajax-Return':
	        		if(typeof(this._return_handler) == 'function') {
	        			this._return_handler.call(this, obj);
	        		}
	        		break;
	        	default:
	        		if(this._object_handler[objName] != 'undefine') {
	        			if(typeof(this._object_handler[objName]) == 'function') {
	        				this._object_handler[objName].call(this, obj);
	        			}
	        		}
	        }
		}
	}
	
	
	for(i=0; i<this._callback_func_user.length; i++) {
		this._callback_func_user[i].call(this,ReqObg);
	}
		
}