// **********************AJAX CORE************************ //

// This is the global that comprises the SINGLETON pattern.
// YOU MUST ALWAYS USE THIS OBJECT (Not class). If you create another instance, it will SEEM to work, until
// things get hot n' heavy. You need to ALWAYS use the same object, as There Can Be Only One.

var	g_ajax_obj = new c_ajax_object();	// This will be the gobal AJAX object. There can be only one...

/******************************************************************
	This class handles "queueing" objects in a pseudo-asynchronous fashion.
	Ajax can't actually handle multiple streams, so we "queue" the requests
	to execute one after another.
*/
function c_ajax_object() {
	// THIS SPACE FOR RENT
}

// Initialize the prototype fields.
c_ajax_object.prototype._requestID                   = 0;
c_ajax_object.prototype._dm_xmlhttprequest_type      = null;		// Used when trying for the correct XMLHTTP object type.
c_ajax_object.prototype._XmlHttpRequestObject        = null;	// This is the HTTP Request Object for this instance.
c_ajax_object.prototype._dm_callback_function        = null;		// The function to be called upon completion of a request.
c_ajax_object.prototype._targObject                  = null;
c_ajax_object.prototype._lock                        = false;
c_ajax_object.prototype._dm_in_obj                   = null;
c_ajax_object.prototype._dm_param                    = null;						// An additional parameter to be passed to the function
c_ajax_object.prototype._dm_partialcallback_function = null;	// A function to be called for the interactive phase
c_ajax_object.prototype._dm_param2                   = null;						// An additional parameter to be passed to that function
c_ajax_object.prototype._dm_phase                    = 0;							// The phase during which this function is called (Default 3).
c_ajax_object.prototype._dm_queue                    = [];				// This is the queue
c_ajax_object.prototype._dm_queue_state              = true;				// This is the queue state
																			// 	false = paused
																			// 	true = normal
c_ajax_object.prototype._dm_committed                = false;					// This is set to true when the HTTPRequest reaches Stage 3.
c_ajax_object.prototype._dm_pre_queue_in_url         = null;			// These are all used for the "pre-queue."
c_ajax_object.prototype._dm_pre_queue_in_obj         = null;
c_ajax_object.prototype._dm_pre_queue_in_callback    = null;
c_ajax_object.prototype._dm_pre_queue_in_method      = null;
c_ajax_object.prototype._dm_pre_queue_in_param       = null;
c_ajax_object.prototype._dm_pre_queue_in_pcallback   = null;
c_ajax_object.prototype._dm_pre_queue_in_param2      = null;
c_ajax_object.prototype._dm_pre_queue_in_c2_phase    = 0;

// New version, created by Jeremy Lucier
c_ajax_object.prototype.GetNewRequestObject = function(){

  // check the dom to see if this is IE or not
  if (window.XMLHttpRequest ){
  
    // Not IE
    this._XmlHttpRequestObject = new XMLHttpRequest();
    
  }else if( window.ActiveXObject ){

    // Hello IE!
    // Instantiate the latest MS ActiveX Objects
    if (this._dm_xmlhttprequest_type) {
      this._XmlHttpRequestObject = new ActiveXObject(this._dm_xmlhttprequest_type);
    }else{

      // loops through the various versions of XMLHTTP to ensure we're using the latest
      var versions = ["Msxml2.XMLHTTP.7.0", "Msxml2.XMLHTTP.6.0", "Msxml2.XMLHTTP.5.0", "Msxml2.XMLHTTP.4.0", "MSXML2.XMLHTTP.3.0", "MSXML2.XMLHTTP", "Microsoft.XMLHTTP"];

      for( var i = 0; i < versions.length ; i++ ){

        try{

          // try to create the object
          // if it doesn't work, we'll try again
	  // if it does work, we'll save a reference to the proper one to speed up future instantiations
  	  this._XmlHttpRequestObject = new ActiveXObject(versions[i]);

  	  if( this._XmlHttpRequestObject ){
	    this._dm_xmlhttprequest_type = versions[i];
	    break;
	  }

        }catch( objException ){
          // trap; try next one
	}

      }

    }
  
  }

};

// QUEUE KILL
c_ajax_object.prototype.QueueFlush = function ( ) {
        if( this._lock ){
          return false;
        }  
        this._XmlHttpRequestObject = null;        // Kill the request object. we're done.
        this._targObject = null;
        this._dm_committed = false;
        this._dm_phase = 0;
        this._requestID = 0;
        this._dm_queue = [];
};

// QUEUE RESET
c_ajax_object.prototype.QueueReset = function ( ) {
        if( this._lock ){
          return false;
        }
        this._XmlHttpRequestObject = null;        // Kill the request object. we're done.
        this._targObject = null;
        this._dm_committed = false;
        this._dm_phase = 0;
        this._requestID = 0;
	this._dm_queue = [];
	this.QueueResume();	// If the queue was paused, it is now re-enabled
};

// QUEUE PAUSE
c_ajax_object.prototype.QueuePause = function ( ) {
	this._dm_queue_state = false;
};

// QUEUE ON
c_ajax_object.prototype.QueueResume = function ( ) {
	this._dm_queue_state = true;
	this.Dequeue();
};

// QUEUE BYPASS
c_ajax_object.prototype.QueueInterrupt = function ( in_url, in_opt, in_method, in_param, in_pcallback, in_param2, in_phase ) {

        this.QueueFlush;         

	var url = in_url;
	this._dm_in_opt = in_opt;	// The basic callback
	var method = in_method;
	this._dm_param = in_param;	// If there is a parameter, we get it here.
	this._dm_partialcallback_function = in_pcallback;	// If there is a partial callback, we get it here.
	this._dm_param2 = in_param2;	// If there is a second parameter, we get it here.
	this._dm_phase = in_phase;	// If there is a second parameter, we get it here.
	
	if ( url && method ) {
  	  this.CallXMLHTTPObject ( url, in_opt, method );
	}
	
	return true;
};

//  INJECT TO ONE
c_ajax_object.prototype.QueueInject = function ( in_url, in_callback, in_method, in_param, in_pcallback, in_param2, in_phase ) {

	this._dm_queue_state = false;

	// Move the queue up one to make room at the start.
	for ( var counter = this._dm_queue.length; counter > 0; counter-- ) {
		this._dm_queue[counter] = this._dm_queue[counter - 1];
	}
		
	this._dm_queue[0] = [in_url, in_callback, in_method, in_param, in_pcallback, in_param2, in_phase];

	this._dm_queue_state = true;	// We don't call DeQueue, so we won't interrupt any request in progress.
};

// INIT REQUEST
c_ajax_object.prototype.CallXMLHTTPObject = function ( in_url, in_obj, in_method, in_param, in_pcallback, in_param2, in_phase ) {

        var bypass = 1;

        if( !this._lock ){

  	  // Set up the "pre queue."
	  this._dm_pre_queue_in_url       =in_url;
	  this._dm_pre_queue_in_obj       =in_obj;
	  this._dm_pre_queue_in_method    =in_method;
	  this._dm_pre_queue_in_param     =in_param;
	  this._dm_pre_queue_in_pcallback =in_pcallback;
	  this._dm_pre_queue_in_param2    =in_param2;
	  this._dm_pre_queue_in_c2_phase  =in_phase;

	  if( (this._dm_pre_queue_in_c2_phase < 1) || (this._dm_pre_queue_in_c2_phase > 3) ){
	    this._dm_pre_queue_in_c2_phase = 3;
	  }

  	  this.Enqueue();
	  return true;

        }

     return false;
};

// ENQUEUE
c_ajax_object.prototype.Enqueue = function ( ) {

        if( this._dm_queue.length <= 3 ){ 

          this._requestID++;

	// Set up the main queue from the prequeue.
	  this._dm_queue[this._dm_queue.length] = [          this._dm_pre_queue_in_url,
                                                             this._dm_pre_queue_in_obj,
	  	                                             this._dm_pre_queue_in_method,
                                                             this._dm_pre_queue_in_param,
                                                             this._dm_pre_queue_in_pcallback,
	  	                                             this._dm_pre_queue_in_param2,
                                                             this._dm_pre_queue_in_c2_phase,
                                                             this._requestID 
                                                             
                                                   ];

	  // As you were...
	  this._dm_pre_queue_in_url=null;
	  this._dm_pre_queue_in_callback=null;
          this._dm_pre_queue_in_obj=null;
	  this._dm_pre_queue_in_method=null;
	  this._dm_pre_queue_in_param=null;
  	  this._dm_pre_queue_in_pcallback=null;
	  this._dm_pre_queue_in_param2=null;
	  this._dm_pre_queue_in_c2_phase=0;
		
	  // If there are no other commands in progress, we start the daisy-chain.
	  if ( !this._XmlHttpRequestObject ) {
		this.Dequeue();
  	  }

        }else{
          this._lock = this._requestID;
        }
};

c_ajax_object.prototype.Dequeue = function ( ) {
	var command = null;
	var ret=false;
	
	if ( this._dm_queue.length && this._dm_queue_state ) {
		command = this._dm_queue[0];
		
		var url                           = command[0];
		this._dm_in_obj                   = command[1];	// The basic callback
		var method                        = command[2];
		this._dm_param                    = command[3];	        // If there is a parameter, we get it here.
		this._dm_partialcallback_function = command[4];	// If there is a partial callback, we get it here.
		this._dm_param2                   = command[5];	// If there is a second parameter, we get it here.
		this._dm_phase                    = command[6];	// If there is a second parameter, we get it here.
                var ID                            = command[7];		

		for ( var counter = 1; counter < this._dm_queue.length; counter++ ) {
			this._dm_queue[counter - 1] = this._dm_queue[counter];
		}
		
		this._dm_queue.length = counter - 1;
	}
	
	if ( url && method ) {
	  ret = this._CallXMLHTTPObject ( url, this._dm_in_obj, method, ID );
	}
	
	return ret;

};

// RUN REQUEST
c_ajax_object.prototype._CallXMLHTTPObject = function ( url, opt, method, requestID ){
 
  try {

    var _targObject = null;

    if( opt ){
      _targObject = getE(opt);
    }
    
    var params = null;

    var theurl; 

    if( method == 'GET' ){
      theurl = url;    
    }else{
      var tp  = url.indexOf('.php');
      var sub = url.substr(tp+4);
      params  = ltrim(sub,'?');
      theurl  = urlSplit[0];
    }

    this.GetNewRequestObject();
    this._XmlHttpRequestObject.open(method, theurl, true);

    if( method != 'GET' ){
      this._XmlHttpRequestObject.setRequestHeader("Method", "POST "+url+" HTTP/1.1");
      this._XmlHttpRequestObject.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
      //this._XmlHttpRequestObject.setRequestHeader("Content-Type", "application/json");
    }
		
    this._XmlHttpRequestObject.onreadystatechange = function(){
    
      var resp;

      if( g_ajax_obj._XmlHttpRequestObject ){       // Don't even bother if we don't have a request object to use.

        if( g_ajax_obj._XmlHttpRequestObject.readyState == 0 ){     // Uninitialized (sent, but no information yet)

        }else if( g_ajax_obj._XmlHttpRequestObject.readyState == 1 ){       // Loading (probably received)

          if( g_ajax_obj._dm_phase == g_ajax_obj._XmlHttpRequestObject.readyState ){

            if( g_ajax_obj._dm_partialcallback_function ){

              if( !ie && g_ajax_obj._XmlHttpRequestObject.responseText ){

                resp = g_ajax_obj._XmlHttpRequestObject.responseText;

              }

              g_ajax_obj._dm_partialcallback_function ( resp, g_ajax_obj._dm_param2 ? g_ajax_obj._dm_param2 : g_ajax_obj._dm_param );

            }

          }

        }else if( g_ajax_obj._XmlHttpRequestObject.readyState == 2 ){       // Loading (probably received)

          if( g_ajax_obj._dm_phase == g_ajax_obj._XmlHttpRequestObject.readyState ){

            if( g_ajax_obj._dm_partialcallback_function ){

              if( !ie && g_ajax_obj._XmlHttpRequestObject.responseText ){

                resp = g_ajax_obj._XmlHttpRequestObject.responseText;

              }

              g_ajax_obj._dm_partialcallback_function ( resp, g_ajax_obj._dm_param2 ? g_ajax_obj._dm_param2 : g_ajax_obj._dm_param );

            }

          }

        }else if( g_ajax_obj._XmlHttpRequestObject.readyState == 3 ){       // Loading (probably received)

 
        }else if( g_ajax_obj._XmlHttpRequestObject.readyState == 4 ){       // Loading (probably received)

          if( g_ajax_obj._XmlHttpRequestObject.responseText ){

            resp = g_ajax_obj._XmlHttpRequestObject.responseText;               
            
            if( typeof(g_ajax_obj._dm_param) == 'function' ){             
               g_ajax_obj._dm_param(resp);
            }else if( sObj ){
              sObj.html = resp;              
              if( !sObj.sliding ){                     
                sObj.fillContents();
              }
            } 

          }  

          if( typeof g_ajax_obj != 'undefined' ) { // Just in case they nuked the object in the callback.

            if( g_ajax_obj._lock == requestID ){
              g_ajax_obj._lock = false;
            }

            g_ajax_obj._XmlHttpRequestObject = null;        // Kill the request object. we're done.
            g_ajax_obj._targObject = null;
            g_ajax_obj._dm_committed = false;
            g_ajax_obj._dm_phase = 0;
            g_ajax_obj.Dequeue();

          }

        }

      }

    };

    this._XmlHttpRequestObject.send(params);
		
    return true;

  }

  catch ( z ) { }
	
  return false;

};

function ajax(url,opt,method,func){
  if( !method ){
    method = 'POST';
  }  
  method = method.toUpperCase();
  return g_ajax_obj.CallXMLHTTPObject(url,opt,method,func);
}

