


var _AjaxMessageCenter = new AjaxMessageCenter();
_AjaxMessageCenter.determinePostOfficeUrl();
var _areBundlingMessagesIntoOneRequest = false;

/**
 * sendAjaxMessage()
 * 
 * Send a single ajax message to the server or append to the queue if called
 * between beginAddingAjaxMessagesToQueue()/sendQueuedAjaxMessages().
 * 
 * @param targetClass string
 * @param targetMethod string
 * @param targetMethodArguments anything (optional)
 * @param callbackFunction function (optional)
 */
function sendAjaxMessage(targetClass, targetMethod, targetMethodArguments, callbackFunction)
{
  message = new AjaxMessage(targetClass, targetMethod, targetMethodArguments, callbackFunction);
  
  _AjaxMessageCenter.appendMessageToQueue(message);
  
  if (!_areBundlingMessagesIntoOneRequest) {
    _AjaxMessageCenter.sendQueuedMessages();
  }
}

/**
 * beginAddingAjaxMessagesToQueue()
 * 
 * After this function has been called, any sendAjaxMessage() calls will be added
 * to a queue and sent when you call sendQueuedAjaxMessages(). Using the queue
 * will bundle multiple messages into a single HTTP request, which is faster and
 * more reliable.
 */
function beginAddingAjaxMessagesToQueue()
{
  if (_areBundlingMessagesIntoOneRequest) {
    alert('WARNING: Cannot nest begin/endSendingAjaxMessages().');
    return;
  }
  
  _areBundlingMessagesIntoOneRequest = true;
}

/**
 * sendQueuedAjaxMessages()
 * 
 * Send any messages in the queue
 */
function sendQueuedAjaxMessages()
{
  if (!_areBundlingMessagesIntoOneRequest) {
    alert('WARNING: endSendingAjaxMessages() called when we are not sending messages.');
    return;
  }
  
  _areBundlingMessagesIntoOneRequest = false;
  
  _AjaxMessageCenter.sendQueuedMessages();
}




function AjaxMessageCenter()
{
  this.messageQueue = new Array();
  this.busyIndicatorRetainCount = 0;
  
  this.appendMessageToQueue = function(message)
  {
    this.messageQueue.push(message);
  }
  
  this.sendQueuedMessages = function()
  {
    messageObjects = new Array();
    for (var i = 0; i < this.messageQueue.length; i++) {
      messageObjects.push(this.messageQueue[i].buildMessageObj());
    }
    
    req = this.buildXHR();
    var thisVar = this;
    var messageQueueCopy = thisVar.messageQueue;
    req.onreadystatechange = function() { thisVar.processXHRStatusChange(req, messageQueueCopy); };
    
    req.open('POST', this.postOfficeUrl);
    req.send(messageObjects.toJSON());
    
    this.messageQueue = new Array();
    this.showBusyIndicator();
  }
  
  this.buildXHR = function()
  {
    var req = false;

    try { req = new XMLHttpRequest(); } catch(e) {} // most browsers
    if (!req) try { req = new ActiveXObject('Msxml2.XMLHTTP'); } catch(e) {} // ie6
    if (!req) try { req = new ActiveXObject('Microsoft.XMLHTTP'); } catch(e) {} // ie5
    if (!req) {
      alert('Error: Your browser does not support AJAX. Please upgrade your browser and try again.'); // unsupported browser
      return null;
    }

    return req;
  }
  
  this.processXHRStatusChange = function(xhrObject, messageObjects)
  {
    // make sure we're finnished loading.
    if (xhrObject.readyState < 4)
      return;
    
    // Make we didn't 404 or anything like that. NOTE: FireFox occasionally logs a wierd exception when executing 'xhrObject.status'.
    if (xhrObject.status != 200) {
      this.hideBusyIndicator();
      return;
    }
      
    // Parse response.
    results = xhrObject.responseText.evalJSON();
    if (results === false) {
      try{
        console.error('ajax server error, response: ' + xhrObject.responseText);
      }
      catch (e)
      {
        // ignore
      }
      this.hideBusyIndicator();
      return;
    }
  
    // check for error
    if (results.error)
		{
      try{
        console.error('ajax error: ' + results.errorMessage)
      }
			catch (e)
			{
        // ignore
      }
		}
    else
    {
      //run callbacks.
      for (var i = 0; i < messageObjects.length; i++) {
        var messageObject = messageObjects[i];
        var result = results[i];
        
        if (messageObject.callbackFunction != null)
          messageObject.callbackFunction(result);
      }
    }
        
    this.hideBusyIndicator();
  }
  
  this.showBusyIndicator = function ()
  {
    this.busyIndicatorRetainCount++;
    
    busyEl = document.getElementById('ajaxmessage-busy');
    if (busyEl != null) busyEl.style.display = (this.busyIndicatorRetainCount > 0) ? 'block' : 'none';
  }
  
  this.hideBusyIndicator = function ()
  {
    this.busyIndicatorRetainCount--;
    
    busyEl = document.getElementById('ajaxmessage-busy');
    if (busyEl != null) busyEl.style.display = (this.busyIndicatorRetainCount > 0) ? 'block' : 'none';
  }
    
  this.determinePostOfficeUrl = function()
  {
    this.postOfficeUrl = '/include/modules/optional/ajax/ajaxpostoffice';
    var pageUrl = document.location.href;
    if (matches = pageUrl.match(/^http:\/\/clients\.cityofcairns\.com\/([^\/]+)/))
      this.postOfficeUrl = '/' + matches[1] + this.postOfficeUrl;
  }
}

function AjaxMessage(targetClass, targetMethod, targetMethodArguments, callbackFunction)
{
  this.targetClass = targetClass;
  this.targetMethod = targetMethod;
  this.targetMethodArguments = targetMethodArguments;
  this.callbackFunction = callbackFunction;

  this.buildMessageObj = function()
  {
    var dataObj = {
      targetClass: this.targetClass,
      targetMethod: this.targetMethod
    }
    
    if (this.targetMethodArguments != null)
      dataObj.targetMethodArguments = this.targetMethodArguments;
    
    if (this.callbackFunction != null)
      dataObj.callbackFunction = this.callbackFunction.toString();
    
    return dataObj;
  }
}

