// *********************************************************************
// *                   EVENTS					       *
// *********************************************************************

// * Ajax_OnLoadFailed(SENDER, EXCEPTION)
// * Ajax_OnAborted(SENDER)
// * Ajax_OnAbortFailed(SENDER, EXCEPTION)
// * Ajax_OnResponseHeadersFailed(SENDER, EXCEPTION)
// * Ajax_OnResponseHeaderFailed(SENDER, EXCEPTION)
// * Ajax_OnNotInitialized(SENDER)
// * Ajax_OnOpened(SENDER)
// * Ajax_OnSended(SENDER)
// * Ajax_OnReceiving(SENDER)
// * Ajax_OnCompleted(SENDER)
// * Ajax_OnGetFailed(SENDER, EXCEPTION)
// * Ajax_OnHeadFailed(SENDER, EXCEPTION)
// * Ajax_OnPostFailed(SENDER, EXCEPTION)

// *********************************************************************
// *                   PUBLIC					       *
// *								       *
// * @group: optional					       	       *
// *********************************************************************
function Ajax(group, asynchronous, prevent_caching)
{
  this.group = group;
  this.prevent_caching = (prevent_caching != undefined) ? prevent_caching : true;
  this.asynchronous = (asynchronous != undefined) ? asynchronous : true;
  this.New();
}

Ajax.prototype =
{
  id: null,
  customs: null,
  mXMLHTTP: null,
  mItems: null,
  mHeaders: null,
  group: null,
  asynchronous: true,
  customRequest: null,
  prevent_caching: true
}

Ajax.prototype.Abort = function()
{
   try
   {
      this.mXMLHTTP.abort();
      this.LoadEvent('Ajax_OnAborted', null);
   }
   catch(e)
   {
      this.LoadEvent('Ajax_OnAbortFailed', (typeof(e) == 'object') ? e : new Exception(0, e));
   }
}

Ajax.prototype.ResponseHeaders = function()
{
   try
   {
      return this.mXMLHTTP.getAllResponseHeaders();
   }
   catch(e)
   {
      this.LoadEvent('Ajax_OnResponseHeadersFailed', (typeof(e) == 'object') ? e : new Exception(0, e));
   }
}

Ajax.prototype.ResponseHeader = function(field)
{
   try
   {
      return this.mXMLHTTP.getResponseHeader(field);
   }
   catch(e)
   {
      this.LoadEvent('Ajax_OnResponseHeaderFailed', (typeof(e) == 'object') ? e : new Exception(0, e));
   }
}

Ajax.prototype.AddRequestHeader = function(field, value)
{
   this.mHeaders[field] = value;
}

Ajax.prototype.Get = function(url)
{
   try
   {
      this.SubmitRequest('GET', url);
   }
   catch(e)
   {
      this.LoadEvent('Ajax_OnGetFailed', (typeof(e) == 'object') ? e : new Exception(0, e));
   }
}

Ajax.prototype.Head = function(url)
{
   try
   {
      this.SubmitRequest('HEAD', url);
   }
   catch(e)
   {
      this.LoadEvent('Ajax_OnHeadFailed', (typeof(e) == 'object') ? e : new Exception(0, e));
   }
}

Ajax.prototype.Post = function(url)
{
   try
   {
      this.SubmitRequest('POST', url);
   }
   catch(e)
   {
      this.LoadEvent('Ajax_OnPostFailed', (typeof(e) == 'object') ? e : new Exception(0, e));
   }
}

Ajax.prototype.Text = function()
{
   return this.mXMLHTTP.responseText;
}

Ajax.prototype.Xml = function()
{
   return this.mXMLHTTP.responseXML;
}

Ajax.prototype.AddRequestParameter = function(key, value)
{
   this.mItems[key] = String(value);
}

Ajax.prototype.ClearRequestParameters = function()
{
   this.mItems = {};
}

Ajax.prototype.ClearRequestHeaders = function()
{
   this.mHeaders = {};
}

Ajax.prototype.ClearCustoms = function()
{
   this.customs = {};
}

// *********************************************************************
// *                   PRIVATE					       *
// *********************************************************************

Ajax.prototype.New = function()
{
  var MYSELF = this;
  this.id = UniqID();
  this.customs = {};
  this.mItems = {};
  this.mHeaders = {};
  /*@cc_on
  @if (@_jscript_version >= 5)
    try
    {
      this.mXMLHTTP = new ActiveXObject("Msxml2.XMLHTTP");
      if(this.asynchronous) { this.mXMLHTTP.onreadystatechange = function() { MYSELF.StateChanged(); }; }
    }
    catch(e)
    {
      try
      {
       	this.mXMLHTTP = new ActiveXObject("Microsoft.XMLHTTP");
        if(this.asynchronous) { this.mXMLHTTP.onreadystatechange = function() { MYSELF.StateChanged(); }; }
      }
      catch(eX) { }
    }
  @end @*/
  
  if (this.mXMLHTTP == null)
  {
     if(typeof XMLHttpRequest != 'undefined')
     {
     	try
     	{
     	   this.mXMLHTTP = new XMLHttpRequest();
     	   if(this.asynchronous) { this.mXMLHTTP.onreadystatechange = function() { MYSELF.StateChanged(); }; }
     	}
   	catch(e)
   	{
  	   this.LoadEvent('Ajax_OnLoadFailed', (typeof(e) == 'object') ? e : new Exception(0, e));
  	}
     } 
     else { this.LoadEvent('Ajax_OnLoadFailed', new Exception(0, 'Your browser does not support XMLHTTPRequest objects.')); }
  }
  
  InstanciateSupervisor();
  supervisor.RegisterGarbage(this, this.id);
}

Ajax.prototype.StateChanged = function()
{
   switch(this.mXMLHTTP.readyState)
   {
      // * not initialized
      case 0 :  this.LoadEvent('Ajax_OnNotInitialized', null);
      		break;
      
      // * open called successfully
      case 1 :  this.LoadEvent('Ajax_OnOpened', null);
      		break;
      
      // * send called successfully
      case 2 :  this.LoadEvent('Ajax_OnSended', null);
      		break;
      
      // * receiving data
      case 3 :  this.LoadEvent('Ajax_OnReceiving', null);
      		break;
      
      // * all data have been received
      case 4 :  this.LoadEvent('Ajax_OnCompleted', new Status(this.mXMLHTTP.status, this.mXMLHTTP.statusText));
      		break;
   }
}

Ajax.prototype.GetParameters = function()
{
   var items = '';
   for(var key in this.mItems)
   {
      if(key != 'xml') // * Firefox fix
      {
         if(items != '') { items += '&'; }
         items += key + "=" + this.mItems[key];
      }
   }
   return items;
}

Ajax.prototype.SubmitRequest = function(type, url)
{
   if(this.prevent_caching)
   {
      url += (url.indexOf('?') != -1) ? '&' : '?';
      url += '_timestamp=' + UniqID();
   }
   this.mXMLHTTP.open(type, url, this.asynchronous);
   for(var key in this.mHeaders)
   { if(key != 'xml') { this.mXMLHTTP.setRequestHeader(key, this.mHeaders[key]); } }
   this.mXMLHTTP.send((this.customRequest) ? this.customRequest : this.GetParameters());
   if(!this.asynchronous) { this.StateChanged(); }
}

// *********************************************************************
// *                   EVENTS					       *
// *********************************************************************

Ajax.prototype.LoadEvent = function(name, object)
{
  try
  {
     name = (this.group) ?  name + '_' + this.group : name;
     eval(name + '(this' + ((object == null) ? ')' : ', object)'));
  }
  catch(e) { }
}

// *********************************************************************
// *                   STATUS					       *
// *********************************************************************

function Status(code, message)
{
   this.code = code;
   this.message = message;
}