//-------------------- ricoAjaxEngine.js - rico ajax engine made suitable for prototype 1.5
AjaxEngine = Class.create();

AjaxEngine.prototype = {

   initialize: function() {
      this.ajaxElements = new Array();
      this.ajaxReplace = new Array();
      this.ajaxObjects  = new Array();
		this.ajaxIframeObservers = new Array();
		this.iframeForms = {};
      this.requestURLS  = new Array();
      this.options = {};
   },

   registerAjaxElement: function( anId, anElement ) {
      if ( !anElement )
         anElement = $(anId);
      this.ajaxElements[anId] = anElement;
   },

	registerReplace : function( anId) {
      this.ajaxReplace[anId] = true;
	},

   registerAjaxObject: function( anId, anObject ) {
      this.ajaxObjects[anId] = anObject;
   },

   registerAjaxFormIframe: function( anId, anForm, anIframe, callback) {
		var anForm = $(anForm);
		this.iframeForms[anId] = anForm;
		var anIframe = $(anIframe);
		if (anForm.target != anIframe.name) {
			throw new Error("The forms target should be the same as the iframe's name");
		}
		if (this.ajaxIframeObservers[anId]) {
			Event.stopObserving(this.ajaxIframeObservers[anId].iframe, "load", this.ajaxIframeObservers[anId].func);
		}
		var func = this._iframeLoad.bindAsEventListener(this, anId, anForm, anIframe, callback);
      this.ajaxIframeObservers[anId] = {"iframe" : anIframe, "func" : func};
		Event.observe(anIframe, "load", func);
   },

   unRegisterAjaxFormIframe : function( anId) {
		if (this.ajaxIframeObservers[anId]) {
			Event.stopObserving(this.ajaxIframeObservers[anId].iframe, "load", this.ajaxIframeObservers[anId].func);
		}
		this.ajaxIframeObservers[anId] = null;
		this.iframeForms[anId] = null;
   },

   registerRequest: function (requestLogicalName, requestURL) {
      this.requestURLS[requestLogicalName] = requestURL;
   },

   sendRequest: function(requestName, options) {
      // Allow for backwards Compatibility
      if ( arguments.length >= 2 )
       if (typeof arguments[1] == 'string')
         options = {parameters: this._createQueryString(arguments, 1)};
	  if (this.iframeForms[requestName] ) {
		  this.iframeForms[requestName].submit();
	  }
	  else {
      	this.sendRequestWithData(requestName, null, options);
	  }
   },

   sendRequestWithData: function(requestName, xmlDocument, options) {
      var requestURL = this.requestURLS[requestName];
      if ( requestURL == null )
         return;

      // Allow for backwards Compatibility
      if ( arguments.length >= 3 )
        if (typeof arguments[2] == 'string')
          options.parameters = this._createQueryString(arguments, 2);

      new Ajax.Request(requestURL, this._requestOptions(options,xmlDocument));
   },

   sendRequestAndUpdate: function(requestName,container,options) {
      // Allow for backwards Compatibility
      if ( arguments.length >= 3 )
        if (typeof arguments[2] == 'string')
          options.parameters = this._createQueryString(arguments, 2);

      this.sendRequestWithDataAndUpdate(requestName, null, container, options);
   },

   sendRequestWithDataAndUpdate: function(requestName,xmlDocument,container,options) {
      var requestURL = this.requestURLS[requestName];
      if ( requestURL == null )
         return;

      // Allow for backwards Compatibility
      if ( arguments.length >= 4 )
        if (typeof arguments[3] == 'string')
          options.parameters = this._createQueryString(arguments, 3);

      var updaterOptions = this._requestOptions(options,xmlDocument);

      new Ajax.Updater(container, requestURL, updaterOptions);
   },

   // Private -- not part of intended engine API --------------------------------------------------------------------

   _requestOptions: function(options,xmlDoc) {
      var sendMethod = 'post';
      (!options) ? options = {} : '';

      if (!options._RicoOptionsProcessed){
      // Check and keep any user onComplete functions
        if (options.onComplete)
             options.onRicoComplete = options.onComplete;
        // Fix onComplete
        if (options.overrideOnComplete)
          options.onComplete = options.overrideOnComplete;
        else
          options.onComplete = this._onRequestComplete.bind(this);
        options._RicoOptionsProcessed = true;
      }

     // Set the default options and extend with any user options
     this.options = {
                     parameters:     options.parameters,
                     postBody:       xmlDoc,
                     method:         sendMethod,
                     onComplete:     options.onComplete
                    };
     // Set any user options:
     Object.extend(this.options, options);
     return this.options;
   },

   _createQueryString: function( theArgs, offset ) {
      var queryString = ""
      for ( var i = offset ; i < theArgs.length ; i++ ) {
          if ( i != offset )
            queryString += "&";

          var anArg = theArgs[i];

          if ( anArg.name != undefined && anArg.value != undefined ) {
            queryString += anArg.name +  "=" + encodeURIComponent(anArg.value) ;
          }
          else {
             var ePos  = anArg.indexOf('=');
             var argName  = anArg.substring( 0, ePos );
             var argValue = anArg.substring( ePos + 1 );
			 queryString += argName + "=" + encodeURIComponent(argValue);

          }
      }
      return queryString;
   },

   _onRequestComplete : function(request) {
      if(!request)
          return;
      // User can set an onFailure option - which will be called by prototype
      if (request.status != 200)
        return;

      this._processAjaxResponses(request.responseXML.getElementsByTagName("ajax-response") );
   },

   _processAjaxResponses : function(ajaxResponseElements) {
      if (ajaxResponseElements == null || ajaxResponseElements.length != 1)
         return;
      this._processAjaxResponse( ajaxResponseElements[0].childNodes );

      // Check if user has set a onComplete function
      var onRicoComplete = this.options.onRicoComplete;
      if (onRicoComplete != null)
          onRicoComplete();
   },

   _processAjaxResponse: function( xmlResponseElements ) {

      for ( var i = 0 ; i < xmlResponseElements.length ; i++ ) {
         var responseElement = xmlResponseElements[i];

         // only process nodes of type element.....
         if ( responseElement.nodeType != 1 )
            continue;

         var responseType = responseElement.getAttribute("type");
         var responseId   = responseElement.getAttribute("id");

         if ( responseType == "object" )
            this._processAjaxObjectUpdate( this.ajaxObjects[ responseId ], responseElement );
         else if ( responseType == "element" ) {
            this._processAjaxElementUpdate( this.ajaxElements[ responseId ], responseElement, this.ajaxReplace[ responseId ]);
            this.ajaxReplace[ responseId ] = false;
         }
      }
   },

   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) { // CDATA node
              contentStr += n.nodeValue;
          }
          else {
            contentStr += xmlSerializer.serializeToString(n);
        }
     }
     return contentStr;
  },


   _processAjaxObjectUpdate: function( ajaxObject, responseElement ) {
      ajaxObject.ajaxUpdate( responseElement );
   },

   _processAjaxElementUpdate: function( ajaxElement, responseElement, doReplace ) {
      if (doReplace == true) {
         $(ajaxElement).replace(this.getContentAsString(responseElement) );
      }
      else {
         ajaxElement.innerHTML = this.getContentAsString(responseElement);
      }
   },

	_iframeLoad: function(event, anId, anForm, anIframe, callback) {
		anForm.reset();

		if (anIframe.contentDocument) {
			var FrameDocument = anIframe.contentDocument;
		}
		else if (anIframe.contentWindow) {
			var FrameDocument = anIframe.contentWindow.document;
		}
		else {
			if (window.frames[anIframe.id]) {
				var FrameDocument = window.frames[anIframe.id].document;
			}
		}
		if (!FrameDocument) {
			return;
		}

		// Fix IE's xml loading
		try {
			var xmlDoc = FrameDocument["XMLDocument"];
		}
		catch(e){}

		if (typeof(xmlDoc) != "undefined") {
			FrameDocument = xmlDoc;
		}
		// Fix IE's xml loading
		this._processAjaxResponses(FrameDocument.getElementsByTagName("ajax-response") );

		if (typeof(callback) == "function") {
			callback(FrameDocument.getElementsByTagName("ajax-response") );
		}
	}

}

var ajaxEngine = new AjaxEngine();

