//===============================================================
//EOL AJAX
//===============================================================
var xmlTool = {
	getContentAsString: function( parentNode )
	{
      return parentNode.xml != undefined ? 
         this._getContentAsStringIE(parentNode) :
         this._getContentAsStringMozilla(parentNode);
	},

	_getContentAsStringIE: function(parentNode)
	{
		var contentStr = "";
		for ( var i = 0 ; i < parentNode.childNodes.length ; i++ )
		{
			var n = parentNode.childNodes[i];
			if (n.nodeType == 4) {contentStr += n.nodeValue;}
			else {contentStr += n.xml;}
		}
		return contentStr;
	},

	_getContentAsStringMozilla: function(parentNode)
	{
		var xmlSerializer = new XMLSerializer();
		var contentStr = "";
		for ( var i = 0 ; i < parentNode.childNodes.length ; i++ )
		{
			var n = parentNode.childNodes[i];
			if (n.nodeType == 4) {contentStr += n.nodeValue;}
			else {contentStr += xmlSerializer.serializeToString(n);}
		}
		return contentStr;
	}
};

var AjaxEOL = new Class({
	Implements: [Events, Options],
	options: {
		method: 'post',
		async: true,
		onRequest: Class.empty,
		onSuccess: Class.empty,
		onFailure: Class.empty,
		onComplete: Class.empty,
		urlEncoded: true,
		encoding: 'utf-8',
		autoCancel: false,
		headers: {},
		data: null,
		update: null,
		evalScripts: false,
		evalResponse: false
	},

	initialize: function(url, options){
		this.setOptions(options);

		this.transport = (window.XMLHttpRequest) ? new XMLHttpRequest() : (window.ie ? new ActiveXObject('Microsoft.XMLHTTP') : false);
		this.addEvent('onSuccess', this.onComplete);

		/*compatibility*/
		//this.options.data = this.options.data || this.options.postBody;
		/*end compatibility*/
		
		if (!['post', 'get'].contains(this.options.method))	this.options.method = 'post';
		
		this.options.isSuccess = this.options.isSuccess || this.isSuccess;
		this.headers = {};
		if (this.options.urlEncoded && this.options.method == 'post'){
			var encoding = (this.options.encoding) ? '; charset=' + this.options.encoding : '';
			this.setHeader('Content-type', 'application/x-www-form-urlencoded' + encoding);
		}
		
		//if (this.options.initialize) this.options.initialize.call(this);

		this.setHeader('X-Requested-With', 'XMLHttpRequest');
		this.setHeader('Accept', 'text/javascript, text/html, application/xml, text/xml, */*');
		this.url = url;
	},

	onStateChange: function(){
		if (this.transport.readyState != 4 || !this.running) return;
		this.running = false;
		var status = 0;
		try {status = this.transport.status;} catch(e){};
		
		if (this.options.isSuccess.call(this, status)) this.onSuccess(); else this.onFailure();
		
		this.transport.onreadystatechange = Class.empty;
	},

	isSuccess: function(status){
		return ((status >= 200) && (status < 300));
	},

	onSuccess: function(){
		this.response = {
			'text': this.transport.responseText,
			'xml': this.transport.responseXML
		};
		this.fireEvent('onSuccess', [this.response.text, this.response.xml]);
		this.callChain();
	},

	onFailure: function(){
		this.fireEvent('onFailure', this.transport);
	},

	setHeader: function(name, value){
		this.headers[name] = value;
		return this;
	},
	request: function(data){
		data = data || this.options.data;
		switch($type(data)){
			case 'element': data = $(data).toQueryString(); break;
			case 'object': data = Object.toQueryString(data);
		}
		//if (this._method) data = (data) ? [this._method, data].join('&') : this._method;
		return this.send(this.url, data);
	},
	send: function(url, data){
		if (this.options.autoCancel) this.cancel();
		else if (this.running) return this;
		this.running = true;
		if (data && this.options.method == 'get'){
			url = url + (url.contains('?') ? '&' : '?') + data;
			data = null;
		}

		this.transport.open(
				this.options.method.toUpperCase(), 
				url, 
				this.options.async);
		
		this.transport.onreadystatechange = this.onStateChange.bind(this);
		if ((this.options.method == 'post') && this.transport.overrideMimeType) this.setHeader('Connection', 'close');

		$extend(this.headers, this.options.headers);
		for (var type in this.headers) 
			try {
				this.transport.setRequestHeader(type, this.headers[type]);
			} catch(e){};

		this.fireEvent('onRequest');
		this.transport.send($pick(data, null));
		return this;
	},
	cancel: function(){
		if (!this.running) return this;
		this.running = false;
		this.transport.abort();
		this.transport.onreadystatechange = Class.empty;
		this.setTransport();
		this.fireEvent('onCancel');
		return this;
	},
	onComplete: function(){
		if( this.response.xml )
		{
			var response = this.response.xml.getElementsByTagName("ajax-response");
			if (response == null || response.length != 1) return;

			var xmlResponseElements = response[0].childNodes ;
			for ( var i = 0 ; i < xmlResponseElements.length ; i++ )
			{
				var responseElement = xmlResponseElements[i];
				if ( responseElement.nodeType != 1 ) continue;
				var responseType = responseElement.getAttribute("type");
				var responseId   = responseElement.getAttribute("id");
				var responseOption   = responseElement.getAttribute("option");
				if ( responseType == "element" ) 
				{
					// si l'ID='@' c'est du Javascript
					if( responseId=="@" )
					{
						var scriptEl = xmlTool.getContentAsString(responseElement);
						var script, regexp = /<script[^>]*>([\s\S]*?)<\/script>/gi;
						if( responseOption == "top")
						{
							// sys_global : voir dans HTML (var sys_global=this;)
							// l'execution des scripts est faite au niveau window.top !!!
							while ((script = regexp.exec(scriptEl))) { var topW=window.top; topW.eval(script[1]);}
						}
						else
						{
							// sys_global : voir dans HTML (var sys_global=this;)
							// l'execution des scripts est faite au niveau document.sys_global... !!!
							while ((script = regexp.exec(scriptEl))) sys_global.eval(script[1]);
						}
					}
					else // sinon , c'est un id à mettre à jour...
					{
						var element=$(responseId);
						// Si on passe l'option top, on cherche un id hors des limites (example iframe)
						if( responseOption == "top") {element=$(window.top.document.body).getElementById(responseId);}
						var IdAndScript = xmlTool.getContentAsString(responseElement);
						element.innerHTML = IdAndScript;
						// si on a du script dans l'Id, on execute...
						var script, regexp = /<script[^>]*>([\s\S]*?)<\/script>/gi;
						while ((script = regexp.exec(IdAndScript))) 
						{
							sys_global.eval(script[1]);
						}
					}
				}
				//processAjaxElementUpdate( this.ajaxElements[ responseId ], responseElement );
				else alert('unrecognized AjaxResponse type : ' + responseType );
			}
		}
		else
		{				
			// methode de base mootools avec , update: <id_object>, ...
			//if (this.options.update) $(this.options.update).setHTML(this.response.text);
			var texte =  this.response.text;
			texte = texte.replace(/&quot;/g,'\"'); // 34 22
			texte = texte.replace(/&amp;/g,'&'); // 38 26
			texte = texte.replace(/&#39;/g,'\''); // 39 27
			texte = texte.replace(/&lt;/g,'<'); // 60 3C
			texte = texte.replace(/&gt;/g,'>'); // 62 3E		
			sys_global.eval(texte);
		}
		
		//if (this.options.evalResponse) eval(this.response.text);
		//if (this.options.evalScripts) this.evalScripts.delay(30, this);
		this.fireEvent('onComplete', [this.response.text, this.response.xml], 20);
	},
	evalScripts: function(){
		var script, regexp = /<script[^>]*>([\s\S]*?)<\/script>/gi;
		while ((script = regexp.exec(this.response.text))) eval(script[1]);
	},
	getHeader: function(name){
		try {return this.transport.getResponseHeader(name);} catch(e){};
		return null;
	}
});

AjaxEOL.implement(new Chain, new Events, new Options);

Element.extend({
	sendEOL: function(options){
		return new AjaxEOL(this.getProperty('action'), $merge({data: this.toQueryString()}, options, {method: 'post'})).request();
	}

});
