/**
 * @author Artur
 */

function MCAjax()
{
	
	//PUBLIC FIELDS
	this.queue                     = []; //Temporary pool for Ajax requests
	
	//PUBLIC SCRIPT CONTAINERS
	
	//PRIVATE FIELDS
	var _formFields                = "";
	var _qidx                      = -1;
	var _scnt                      = []; //Temporary pool for script container
	
	var _queueBufferSize           = 100;
	var _scriptContainerBufferSize = 100;
	
	var AJAXDB_PATH                = "/todavida/nutrivida/DAO/AjaxDB.asp";
	
	//EVENTS
	this.onException = function(){};

	//PUBLIC METHODS
	/**
	 * @author Artur de Paula Ribeiro
	 * @method load
	 * @param {String} url
	 * @param {Object} c
	 * @return MCAjaxQueue
	 * @since 31/03/2007
	 * Carrega uma URL para um container HTML utilizando AJAX
	 */
	this.load = Delegate(this, function(url, c, dr)
	{
		var q = new MCAjaxQueue(url, c == undefined ? _getScriptContainer() : c, true);
		q.displayResult = dr == undefined ? false : dr;
		q.setRequest(_createRequest());
		if (q.request != undefined)
		{
			if (++_qidx > _queueBufferSize)
			{
				for (var i = 0; i < this.queue.length; i ++)
				{
					this.queue[i].dispose();
					this.queue[i] = null;
				}
				this.queue.splice(0, this.queue.length);
				this.queue = null;
				this.queue = [];
				_qidx = 0; 
			} 
			q.index = this.queue.push(q) - 1;
			q.send();
			return q;
		}
		return undefined;
	});

	/**
	 * @author Artur de Paula Ribeiro
	 * @method submitForm
	 * @param {MCFormMapping} formMapping
	 * @param {Boolean} validate
	 * @return MCAjaxQueue
	 * @since 31/03/2007
	 * Realiza submit do formMapping informado
	 */
	this.submitForm = Delegate(this, function(formMapping, validate)
	{
		if (validate == undefined || validate)
		{
			if (!formMapping.validate())
			{
				return {};
			}
		}
		
//		var action = formMapping.form.length == 1 ? formMapping.form[0].action : formMapping.action;
		var action = formMapping.action;
		return this.load(action + "?" + formMapping.getQueryStringData(), _getScriptContainer(), false);
	});
	
	//PRIVATE METHODS
	/**
	 * @author Artur de Paula Ribeiro
	 * @method _getScriptContainer
	 * @return HTMLElement
	 * @since 31/03/2007
	 * Cria um container temporário, para ser utilizado nas requisições Ajax 
	 */
	var _getScriptContainer = Delegate(this, function()
	{
		if (_scnt.length >= _scriptContainerBufferSize)
		{
			for (var i = 0; i < _scnt.length; i ++)
			{
				document.body.removeChild(_scnt[i]);
				_scnt[i] = null;
				delete(_scnt[i]);				
			}
			_scnt.splice(0, _scnt.length);
			_scnt = null;
			delete(_scnt);
			_scnt = [];			
		}
		
		_scnt.push(document.createElement("div"));
		_scnt[_scnt.length - 1].style.display = "none";
		
		document.body.appendChild(_scnt[_scnt.length - 1]);
		
		return _scnt[_scnt.length - 1];
	});
	
	
	/**
	 * @author Artur de Paula Ribeiro
	 * @method submitForm
	 * @param {HTMLElement} pNode - ParentNode
	 * @return void
	 * @since 31/03/2007
	 * Monta QueryString com os campos dentro de um HTMLElement
	 */
	var _getFieldsInNode = Delegate(this, function(pNode)
	{
		for (var p in pNode.childNodes)
		{
			var node = pNode.childNodes[p];
			if (node.tagName != undefined)
			{
				if (node.tagName.toLowerCase() == "input")
				{
					if (node.type == "text" || node.type == "password")
					{
						_formFields += "&" + node.id + "=" + node.value;
					}
				}
				else if (node.tagName.toLowerCase() == "select")
				{
					_formFields += "&" + node.id + "=" + node.options[node.selectedIndex].value;
				}
			}
			_getFieldsInNode(node);
		}
	});

	
	/**
	 * @author Artur de Paula Ribeiro
	 * @method __createRequest
	 * @return void
	 * @since 31/03/2007
	 * Método de criação do objeto XMLHTTPRequest utilizado nas requisições Ajax 
	 */
	var _createRequest = function()
	{
		try
		{
			return new ActiveXObject("Msxml2.XMLHTTP");
		}
		catch(e){}
		try
		{
			return new ActiveXObject("Microsoft.XMLHTTP");
		}
		catch(e){}
		try
		{
			return new XMLHttpRequest();
		}
		catch(e){}
		onException("AJAX não suportado pelo navegador.");
		return undefined;
	}
	
}

/**
 * @author Artur de Paula Ribeiro
 * @classDescription Classe que representa a fila de requisições Ajax
 * @param {String}  m     Método da requisição (POST/GET)
 * @param {String}  u     URL
 * @param {String}  c     htmlContainer onde será renderizado o resultado da requisição
 * @param {Boolean} es   Indica se os scripts da URL carregada serão executados
 * @since 31/03/2007
 * Método de criação do objeto XMLHTTPRequest utilizado nas requisições Ajax 
 */
function MCAjaxQueue(u, c, es)
{
	this.url = u;
	this.htmlContainer = c;
	this.request = undefined;
	this.index = undefined;
	this.responseData = undefined;
	this.execScripts = (es == undefined || es == null ? true : es);
	this.displayResult = false;

	//PRIVATE CONSTANTS
	var READY_STATE_COMPLETED      = 4;
	var REQUEST_STATUS_OK          = 200;
	var REQUEST_STATUS_ERROR       = 500;
	
	//EVENTS
	this.onComplete = function(){};
	this.onBeforeComplete = function(){};
	this.onException = function(){};
	
	this.render = Delegate(this, function()
	{
		try
		{
			var rt = this.request.responseText;
		}
		catch(e)
		{
			alert(request.readyState + "|" + request.status)
		}
/*		if (rt != undefined && rt != "null")
		{
			this.htmlContainer.innerHTML = rt;
			if (this.execScripts)
			{
				rt.evalScripts();
			}
		}*/
	});
	
	this.setRequest = Delegate(this, function(r)
	{
		this.request = r;
		this.request.onreadystatechange = _onRequestReadyStateChange;
	});
	
	this.send = Delegate(this, function()
	{
		this.request.open("GET", this.url, true);
		this.request.setRequestHeader('Content-Type','application/x-www-form-urlencoded;charset=ISO-8859-1');
//		this.request.setRequestHeader('Content-Type','charset=ISO-8859-1');
//		this.request.setRequestHeader("encoding", "ISO-8859-1");
//		this.request.open("POST", this.url + (this.url.indexOf("?") == -1 ? "?" : "&") + "QueueIndex=" + this.index, true);
		
		this.request.send(null);
	});
	
	this.toString = Delegate(this, function()
	{
		return "{htmlContainer:" + this.htmlContainer + ",method=" + this.method + ", url=" + this.url + "}";
	});
	
	var _onRequestReadyStateChange = Delegate(this, function()
	{
		if (this.request.readyState == READY_STATE_COMPLETED)
		{
			switch(this.request.status)
			{
				case REQUEST_STATUS_OK:
					if (this.displayResult)
					{
						MCPopUp.showHTML(this.request.responseText);
					}
					this.onBeforeComplete(this);
					if (this.htmlContainer != undefined)
					{
						this.render();
					}
					try
					{
						eval("this.responseData = " + this.request.responseText);
						if (!this.responseData instanceof Object)
						{
							this.responseData = undefined;
						}
					}
					catch(e)
					{
						alert("Erro ao vincular dados: " + this.request.responseText);
					}
					this.onComplete(this);
					break;
				default :
					MCPopUp.showHTML(this.request.responseText);
			}
		}
	});
	
	this.dispose = Delegate(this, function()
	{
		this.url = null;
		this.htmlContainer = null;
		this.request = null;
		this.index = null;
		this.responseData = null;
		this.execScripts = null;
		
		this.onComplete = null;
		this.onBeforeComplete = null;
		this.onException = null;
		
		this.render = null;
		this.setRequest = null;
		this.send = null;
		this.toString = null;
		_onRequestReadyStateChange = null;
		this.dispose = null;
	});
	
}