// remote scripting library
// (c) copyright 2005 modernmethod, inc
// Changes (c) copyright 2006-2010 phloc systems

var sajax_debug_mode = false;
var sajax_requests = new Array();

function _sajax_debug(text) {
  if ((sajax_debug_mode) && text)
    alert(text);
}

function _sajax_create_object() {
  _sajax_debug("_sajax_create_object() called..")
 
  // Seems like IE has difficulties with XMLHttpRequest (see mail Ulli Starkl 2010/03)
  // -> Using ActiveX helps...
  if (window.ActiveXObject) {
    var msxmlhttp = new Array('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 < msxmlhttp.length; i++) {
      try {
        var httpObj = new ActiveXObject(msxmlhttp[i]);
        return httpObj;
      } catch (ex) {}
    }
  }

  // Use standard XMLHttpRequest request object 
  if (typeof XMLHttpRequest != "undefined")
    return new XMLHttpRequest();

  throw new Error('XMLHttp (AJAX) not supported');
}

function sajax_cancel() {
  for (var i = 0; i < sajax_requests.length; i++)
    sajax_requests[i].abort();
}

/**
 * @param sDesiredURI 
 *   The AJAX URL to use; if null then sajax_remote_uri is used
 *   
 * @param sFuncName 
 *   The name of the AJAX function to invoke. May not be null.
 *   
 * @param aCallback
 *   The callback function to be invoked once the server returns. Maybe null,
 *   a function to be invoked or an object {callback:xxx; extra_data:xxx;}
 *
 * @param aFuncArgs
 *   Optional set of arguments to be passed to the AJAX function. May be null.
 */
function sajax_do_call(sDesiredURI, sFuncName, aCallback, aFuncArgs) {
  var uri = sDesiredURI ? sDesiredURI : sajax_remote_uri;

  _sajax_debug("in sajax_do_call()\nuri = " + uri);
  if (typeof uri == "undefined")
    alert("ERROR: AJAX Remote URI is undefined!");

  // create POST data
  var post_data = "rsname=" + encodeURIComponent(sFuncName);
  post_data += "&rsrnd=" + new Date().getTime();
  if (aFuncArgs)
    for (var i = 0; i < aFuncArgs.length; i++)
      post_data += "&rsargs[]=" + encodeURIComponent(aFuncArgs[i]);
  _sajax_debug("uri = " + uri + "\npost_data = " + post_data);

  var x = _sajax_create_object();
  x.open("POST", uri, true);
  sajax_requests[sajax_requests.length] = x;
  x.setRequestHeader("Method", "POST " + uri + " HTTP/1.1");
  x.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
  x.onreadystatechange = function() {
    if (x.readyState != 4) return;

    _sajax_debug("received " + x.responseText);

    // trim
    var txt = x.responseText.replace(/^\s*|\s*$/g, "");
    var status = txt.charAt(0);
    var data = txt.substring(2);

    if (status == "") {
      // let's just assume this is a pre-response bailout and let it slide for now
    } else
      if (status == "-") {
        alert("ERROR: AJAX response: " + data);
      } else {
        try {
          var callback;
          var extra_data = false;
          if (typeof aCallback == "object") {
            callback = aCallback.callback;
            extra_data = aCallback.extra_data;
          } else {
            callback = aCallback;
          }
          
          var res = null;
          try {
            res = eval(data);
          } catch (ex) {
            alert("ERROR: AJAX caught eval error " + ex + "!\nTo eval: " + data);
          }
          
          // callback may be null (e.g. for logging!)
          if (callback)
            callback(res, extra_data);
        } catch (ex) {
          var sMessage = "ERROR: AJAX caught in callback: " + ex + "!\n" +
                         "Func: " + sFuncName + "\n" +
                         "Args: " + aFuncArgs + "\n" +
                         "URI: " + uri + "\n" +
                         "Callback: " + callback;
          alert(sMessage);
          var aStackTrace = printStackTrace({ e:ex });
          // log via AJAX to server(recursive call!) - avoid indefinite recursion!
          if (sFuncName == "log")
            alert(sStackTrace);
          else
            phloc_server_log(sDesiredURI, sMessage + "\n" + aStackTrace.join ("\n"), "error");
        }
      }
  }

  _sajax_debug(sFuncName + "\nuri = " + uri + "\n/post = " + post_data);
  x.send(post_data);
  _sajax_debug(sFuncName + " waiting...");
  delete x;
  return true;
}

/**
 * Specialized function for doing a server-side logging 
 * @param sDesiredURI AJAX URI to use. Pass <code>null</code> if unsure.
 * @param sMessage The message to be logged.
 * @param sLogLevel The log level to be used. May be <code>null</code>.  
 * @param sLoggerName The name of the logger to use. May be <code>null</code>.
 */
function phloc_server_log (sDesiredURI, sMessage, sLogLevel, sLoggerName) {
  sajax_do_call(sDesiredURI, "log", null, [sMessage, sLogLevel, sLoggerName]);
}
