O3Global.Ajax = new function()
{
  // Page history
  var aPages = new Array();

  // Quick-swap a div
  function loadDiv(sModule, sAction, sDiv, vPostData, fncCallback, bForceReload)
  {
    // Uncollapse div
    if(sDiv == 'topbar')
      Collapse.show(Collapse.TOP);
    if(sDiv == 'menu')
      Collapse.show(Collapse.LEFT);
    if(sDiv == 'right')
      Collapse.show(Collapse.RIGHT);
    if(sDiv == 'bottom')
      Collapse.show(Collapse.BOTTOM);

    // Check if a reload must happen
    if(!bForceReload)
    {
      // Check this div
      var aDiv = aPages[sDiv];
      if(aDiv)
      {
        if(aDiv['module'] == sModule && aDiv['action'] == sAction && (aDiv['postdata'] == vPostData || O3Global.Types.arrayCompare(aDiv['postdata'], vPostData)))
        {
          // Don't reload
          if(fncCallback)
            fncCallback();

          return;
        }
      }
    }

    // Store this request
    aPages[sDiv] = new Array();
    aPages[sDiv]['module']   = sModule;
    aPages[sDiv]['action']   = sAction;
    aPages[sDiv]['postdata'] = vPostData;

    var oRequest = new O3Ajax();
    var oPane    = O3Global.DOM.getById(sDiv);
	
    if(vPostData)
    {
      if(O3Global.Types.isArray(vPostData))
        oRequest.addPostData(vPostData);
      else
        oRequest.addRawPostData(vPostData);
    }
    if(fncCallback)
      oRequest.setCallback(fncCallback);

    // trigger disabled
    announceLoading(sDiv);

    oRequest.setContainer(sDiv);
    oRequest.requestPage(sModule, sAction);
  }

  // Reload a div
  function reloadDiv(sDiv, sModule, sAction, vPostData, fncCallback, bOneSidedMatch, aExtraPost)
  {
    // Check if we have data on this div
    var aDiv = aPages[sDiv];
    if(!aDiv)
      return;

    // If no module is set, just push a reload
    if(!sModule)
      loadDiv(aDiv['module'], aDiv['action'], sDiv, aDiv['postdata'], fncCallback, true);
    else
    {
      // Only reload if all params are the same
      if(aDiv['module'] == sModule && aDiv['action'] == sAction && (aDiv['postdata'] == vPostData || O3Global.Types.arrayCompare(vPostData, aDiv['postdata'], bOneSidedMatch)))
      {
        // Add extra, if possible
        if(aExtraPost && O3Global.Types.isArray(vPostData) && O3Global.Types.isArray(aExtraPost))
        {
          for(var s in aExtraPost)
            vPostData[s] = aExtraPost[s];
        }

        loadDiv(sModule, sAction, sDiv, vPostData, fncCallback, true);
      }
    }
  }

  // Quick-load XML
  function loadXML(sModule, sAction, vPostData, fncCallback, fncErrorCallback)
  {
    var oRequest = new O3Ajax();

    if(vPostData)
    {
      if(O3Global.Types.isArray(vPostData))
        oRequest.addPostData(vPostData);
      else
        oRequest.addRawPostdata(vPostData);
    }

    if(fncCallback)
      oRequest.setHandler(AjaxCodeConfig.OK, fncCallback);
    if(fncErrorCallback)
      oRequest.setHandler(AjaxCodeConfig.ERROR, fncErrorCallback);

    oRequest.requestXML(sModule, sAction);
  }

  function deserializeXML(oXML, oObject)
  {
    // Check for childnodes
    var aNodes = oXML.childNodes;
    if(!aNodes || aNodes.length == 0)
      return;

    // Loop the XMLs childnodes
    for(var i = 0; i < aNodes.length; i++)
    {
      // Fetch node & name
      var oNode = aNodes[i];
      if(!oNode.firstChild)
        continue;

      var sName = oNode.nodeName;
      if(!sName || sName.length == 0)
        continue;

      // Fetch the setter
      var fncSet = eval('oObject.set' + sName);
      if(typeof fncSet != 'function')
        continue;

      // Set the value
      fncSet(oNode.firstChild.data);
    }
  }

  function announceLoading(id)
  {
    var oPane = O3Global.DOM.getById(id);
    if(oPane)
    {
      var oWorkingData = O3Global.DOM.getById('workingdata');
      var newHtml      = oWorkingData ? oWorkingData.innerHTML : '';
      oPane.innerHTML  = newHtml;// + oPane.innerHTML;
      oPane.disabled   = true;
    }
  }

  function clearEntry(sDiv)
  {
    if(aPages[sDiv])
      aPages[sDiv] = null;
  }

  // Bind public functions
  this.loadDiv        = loadDiv;
  this.reloadDiv      = reloadDiv;
  this.loadXML        = loadXML;
  this.deserializeXML = deserializeXML;
  this.clearEntry     = clearEntry;
}