/********************************************************************
 Clean v2.0, AJAX Engine 
 Copyright (c) 2005-2006 Carlos Eduardo Goncalves (cadu.goncalves@gmail.com)
 
 This program is free software, you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation.
*********************************************************************/

/**
* @Class: Message
* <p>
*   Placeholder for AJAX message's paremeters
* </p>   
*/
function Message(){
  this.id = null;	
  this.method = null;
  this.address = null;
  this.xslt = null;
  this.value = null;
  this.document = null;
  this.consumer = null;	
  this.onChange = null;
  this.onError = null;  
  this.callback = null;
  this.params = null;
}

/**
* @Class: Connection
* <p>
*   Responsable to start/stop request
* </p>   
*/
function Connection(){
}

Connection.sendMessage = function(msg){
  try{
	var wrapper = MessageQueue.add(msg);
    msg.id = wrapper.id;	
    wrapper.request.send(msg.value);  
    return msg.id; 	
  } catch(e){
  	Connection.reportException(msg, e);
  }
}

Connection.sendFormByMessage = function(msg, form){
  try{	
    msg.method = "POST";  
    msg.value = ParserTool.formToUtf(form);	
    wrapper = MessageQueue.add(msg);
    msg.id = wrapper.id;	
    wrapper.request.setRequestHeader("Content-Type","application/x-www-form-urlencoded;charset=UTF-8");  
    wrapper.request.send(msg.value);  
    return msg.id; 	
  } catch(e){Connection.reportException(msg, e);}
}

Connection.abortMessage = function(id){
  if(isNaN(id)) 
    return
  try{
    if(MessageQueue.messages[id] != null){
      MessageQueue.messages[id].request.abort();
      MessageQueue.messages[id] = null;
    }
  } catch(e){Connection.reportException(MessageQueue.messages[id], e);}
}

Connection.reportException = function(msg, e){
  if((msg == null) || (msg.onError == null))
    throw e;
  else
    msg.onError(e);
}

/**
* @Class: MessageQueue
* <p>
*   Implements message queue control
* </p>   
*/
function MessageQueue(){
}

MessageQueue.messages = new Array();		

MessageQueue.add = function (Message){ 
  try{
    var wrapper = new MessageWrapper();
    wrapper.wrap(Message);
    // MessageQueue.messages.push(wrapper);	  
    MessageQueue.messages[MessageQueue.messages.length] = wrapper;	  
    return wrapper;
  } catch(e){throw e;}
}

/**
* @Class: MessageWrapper
* <p>
*  Core class that wraps AJAX messages and builds  
*  objects needed for XML request and XSLT processing
* </p>   
*/

function MessageWrapper(){
}

MessageWrapper.prototype.buildRequest = function (){
  try{
    obj = (typeof XMLHttpRequest != "undefined") ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP");	
    return obj;
  } catch(e){throw "1. Browser does not support HTTPRequest features required by Clean engine";}	
}

MessageWrapper.prototype.loadFile = function (url){
  try{
    req = this.buildRequest();
    req.open("GET", url, false);
    req.send('');
    return req.responseXML;
  } catch(e){throw e;}
}

MessageWrapper.prototype.transform = function (orign, style){
  try{
    if (typeof XSLTProcessor != "undefined"){			
	  proc = new XSLTProcessor();
	  proc.importStylesheet(style);
	  return (new XMLSerializer()).serializeToString(proc.transformToDocument(orign));
    }
    else{	
	  proc = new ActiveXObject("Microsoft.XMLDOM");  
	  proc.async = "false";	  
	  proc.load(orign);	
	  return proc.transformNode(style);	
    }
  } catch(e){throw "2. Browser does not support XSLT features required by Clean engine";}	
}

MessageWrapper.prototype.wrap = function(msg){
  try{	
    if((msg.method.toUpperCase() != "POST") && (msg.method.toUpperCase() != "GET"))
	  msg.method = "POST";	
    if(msg.xslt != null)
		this.style = this.loadFile(msg.xslt);  
    this.id = MessageQueue.messages.length;  	
    this.consumer = msg.consumer; 
    this.document = msg.document; 
	this.address = msg.address;	
    this.request = this.buildRequest();
    this.request.open(msg.method, msg.address);
    this.onError = msg.onError;
    if(msg.onChange != null){  
	  this.request.onreadystatechange = msg.onChange;   
    } else {
	  this_ = this;		  
	  this.request.onreadystatechange = function(){ 
	    if(this_.request.readyState == 4){		    
		  if(this_.request.status == 200 || this_request.status == 0 ) {
		    locator = new DomIterator(this_.document);
		    if(this_.style != null) {
			  locator.applyValue(this_.consumer, this_.transform(this_.request.responseXML, this_.style));
		     } else {
			  locator.applyValue(this_.consumer, this_.request.responseText);
			  if ( msg.callback != null ) {
			  	eval(msg.callback+'("'+msg.params+'")');
			  }
			 }
		  } else {
		    e = new String("AJAX request failed: " + this_.address);
			if(this_.onError != null)
			  this_.onError(e);
			else
			  throw e;
		  }
		  MessageQueue.messages[this_.id] = null;			
	    }
	  };  	  
    }
  } catch(e){throw e;}
}

/**
* @Class: DomIterator
* <p>
*  Implements DOM features
* </p>   
*/

function DomIterator(doc){
	this.doc = doc;
}
	
DomIterator.prototype.getValue = function(id){
  if ( id == null ) return;

  try{
	var value;
    e = this.doc.getElementById(id);
    iframes = this.doc.getElementsByTagName("iframe");
    for(var i = 0; i <= iframes.length; ++i){
	  if(iframes[i] != null) {
  	    if(iframes[i].id == e.id){
	        return(e.contentWindow.document.body.innerHTML);
	    }
	  }
    }
    if(e.innerHTML != null){
       return(e.innerHTML);	  
    }
  } catch(e){throw "4. Browser does not support DOM features required by Clean engine";}
}



DomIterator.prototype.applyValue = function(id, value){
  if ( id == null ) return;

  try{
    //value = value.replace(/^\s+|$\s+/, "");
    e = this.doc.getElementById(id);
    iframes = this.doc.getElementsByTagName("iframe");
    for(var i = 0; i <= iframes.length; ++i){
	  if(iframes[i] != null) {
  	    if(iframes[i].id == e.id){
  	        e.contentWindow.document.body.innerHTML = value;
	        return;
	    }
	  }
    }
    if(e.innerHTML != null){
       e.innerHTML = value;	  
    }
  } catch(e){throw "3. Browser does not support DOM features required by Clean engine";}
}

/**
* @Class: ParserTool
* <p>
*  Multi-purpose parser
* </p>   
*/

function ParserTool(){
}

ParserTool.formToUtf = function(form){
  var utf = "";
  try{
    for(var i = 0;i < form.elements.length; ++i){  
      switch(form.elements[i].type.toLowerCase()){	  
	   	case "button": break;
		case "reset": break;	
	    case "radio":
	      if(form.elements[i].checked){
		   utf += form.elements[i].name + "=" + escape(form.elements[i].value) + "&";
		  }
 	      break;		
	    case "checkbox":
	      if(form.elements[i].checked){
		   utf += form.elements[i].name + "=" + escape(form.elements[i].value) + "&";
		  }
 	      break;	
	    case "select-one":
          utf += form.elements[i].name + "=" + form.elements[i].options[form.elements[i].selectedIndex].value + "&";
          break;
	    case "select-multiple":
	      for(var v = 0; v < form.elements[i].options.length; ++v){
            if(form.elements[i].options[v].selected){
		      utf += form.elements[i].name + "=" + form.elements[i].options[v].value + "&";
		    }
		  }
          break;		
	    default:
	      utf += form.elements[i].name + "=" + escape(form.elements[i].value) + "&";
	      break;	  
      }
    }
    utf = utf.substr(0,(utf.length - 1));
    return utf;
  } catch(e){throw e;}
}

