// The ajax module also requires a version of o2escape.js (formFunctions.js? temporaryMessage.js?)
// XXX Find out where the "undefined" strings come from and get rid of them.

o2.require( "/o2www/js/o2escape.js"    );
o2.require( "/o2www/js/html2dom.js"    );
o2.require( "/o2www/js/util/urlMod.js" );

var o2xmlHttpRequest = new Array();
var ajaxIframeId = "o2ajaxIframe";
var _timeoutHandler = new Object();

function o2ajaxAddIframe() {
  if (window.XMLHttpRequest) {
    return;
  }
  var iframe = document.createElement("iframe");
  iframe.setAttribute("id", ajaxIframeId);
  iframe.setAttribute("onload", "ajaxHandleServerResponseIframe();");
  iframe.style.display = "none";
  document.body.appendChild(iframe);
}

// Synchronous "ajax" call
function sAjaxCall(params) {
  return ajaxCall(params, true);
}

function ajaxCall(params, isSynchronous) {
  isSynchronous = isSynchronous || false;
  var paramsString = "";

  //20090916 nilschd adding support for timeout in seconds
  var timeout =0;
  if (params.timeout && parseInt(params.timeout) > 0) {
    timeout = parseInt( params.timeout );
  }

  // Make it possible to use css to do something with target, so the user can see that something is going to happen.
  // Setting class=activeAjaxTarget on all targets
  var targets = _ajaxGetTargetsAsArray( params.target ? params.target.toString() : "" );
  for (var i = 0; i < targets.length; i++) {
    var elm = document.getElementById( targets[i] );
    if (elm) {
      o2.addClassName(elm, "activeAjaxTarget");
    }
  }

  var src = params.serverScript;
  if (src && src.indexOf("?") != -1) {
    var queryString = src.substring( src.indexOf("?")+1 );
    var parameters = queryString.split("&");
    for (var i = 0; i < parameters.length; i++) {
      var paramAndValue = parameters[i].split("=");
      var name  = paramAndValue[0];
      var value = paramAndValue[1];
      paramsString += o2escape(name) + "=" + o2escape(value) + "&";
    }
    src = src.substring( 0, src.indexOf("?") );
  }
  else if (!src) {
    // Don't call o2escape on the param values if urlMod parameters have been used.
    src = o2.urlMod.urlMod(params);
    paramsString = src.substring( src.indexOf("?")+1 );
    if (paramsString) {
      paramsString += "&";
    }
    if (src.indexOf("?") !== -1) {
      src = src.substring( 0, src.indexOf("?") );
    }
  }
  
  if (typeof(params.params) !== "string"){
    var qsp = new Array();
    for (var key in params.params) {
      qsp.push( key + "=" + o2escape(params.params[key]) );
    }
    params.params = qsp.join("&");
  }

  if (params.params) {
    paramsString += params.params + "&";
  }
  // Escape params:
  for (var key in params) {
    if (key !== "params" &&  typeof(params[key]) !== "function" ) {
      params[key] = o2escape( params[key] );
    }
  }
  paramsString
    += "target="               + params.target              + "&handler="      + params.handler + "&where="     + params.where
    +  "&history="             + params.history             + "&onError="      + params.onError + "&onSuccess=" + params.onSuccess
    +  "&ignoreMissingTarget=" + params.ignoreMissingTarget + "&debug="        + params.debug   + "&isAjaxRequest=1"
    +  "&ajaxId="              + params.ajaxCallId          + "&errorHandler=" + params.errorHandler;
  var ajaxId = params.ajaxCallId  ||  parseInt( 1000000*Math.random() );
  delete o2xmlHttpRequest[ajaxId];
  if (window.XMLHttpRequest) {
    try {
      o2xmlHttpRequest[ajaxId] = new XMLHttpRequest();
    }
    catch (e) {
      delete o2xmlHttpRequest[ajaxId];
    }
  }
  else if (window.ActiveXObject) { // branch for IE/Windows ActiveX version
    try {
      o2xmlHttpRequest[ajaxId] = new ActiveXObject("Msxml2.XMLHTTP");
    }
    catch (e) {
      try {
        o2xmlHttpRequest[ajaxId] = new ActiveXObject("Microsoft.XMLHTTP");
      }
      catch (e) {
        delete o2xmlHttpRequest[ajaxId];
      }
    }
  }
  if (o2xmlHttpRequest[ajaxId]) {
    paramsString += "&xmlHttpRequestSupported=1&o2AjaxEncoding=" + getO2escapeEncoding();
    if (!isSynchronous) {
      o2xmlHttpRequest[ajaxId].onreadystatechange = ajaxHandleServerResponseXmlHttp;
    }
    o2xmlHttpRequest[ajaxId].open("POST", src, !isSynchronous); // Third parameter: true means asynchronous, false is synchronous
    o2xmlHttpRequest[ajaxId].send(paramsString);
    if (isSynchronous) {
      if ( typeof(params.handler) === "function" ) {
        o2xmlHttpRequest[ajaxId].o2AjaxCallbackHandler = params.handler;
      }
      return ajaxParseResponse(ajaxId);
    }
    if (timeout > 0) {
      _timeoutHandler[ajaxId] = params.errorHandler != null  ?  params.errorHandler  :  "_noErrorHandler_";
      setTimeout("ajaxCheckTimeoutOnAjaxId(" + ajaxId + ")", timeout*1000);
    }
    if ( typeof(params.handler) === "function" ) {
      o2xmlHttpRequest[ajaxId].o2AjaxCallbackHandler = params.handler;
    }
  }
  else { // Use a hidden iframe (xmlHttpRequest not supported)
    if (src.indexOf("?") == -1) {
      src += "?";
    }
    else {
      src += "&";
    }
    src += paramsString + "&xmlHttpRequestSupported=0";
    document.getElementById(ajaxIframeId).src = src;
  }
}

//20090916 nilschd adding support for timeout in seconds
function ajaxCheckTimeoutOnAjaxId(ajaxId) {
  if ( _timeoutHandler[ajaxId] != null &&  o2xmlHttpRequest[ajaxId] != null && o2xmlHttpRequest[ajaxId].readyState < 4) { // 
    // console.log('ajaxId timeout:'+ ajaxId);
    o2xmlHttpRequest[ajaxId].onreadystatechange = function() {}; //work around for mozilla bug
    o2xmlHttpRequest[ajaxId].abort();
    delete o2xmlHttpRequest[ajaxId];

    if (_timeoutHandler[ajaxId] != "_noErrorHandler_") {
      try {
        eval(_timeoutHandler[ajaxId] + "({result:'timeout'});");
      }
      catch(e) {}
    }
  }
  delete _timeoutHandler[ajaxId];
}

function ajaxHandleServerResponseXmlHttp() {
  // only if o2xmlHttpRequest shows "loaded"
  for (ajaxId in o2xmlHttpRequest) {
    if (o2xmlHttpRequest.hasOwnProperty(ajaxId)) {
      ajaxParseResponse(ajaxId);
    }
  }
}

function ajaxParseResponse(ajaxId) {
  if (o2xmlHttpRequest[ajaxId] && o2xmlHttpRequest[ajaxId].readyState == 4) {
    // only if "OK"
    // alert(o2xmlHttpRequest.readyState+" "+o2xmlHttpRequest.status+" "+o2xmlHttpRequest.responseText);
    if (o2xmlHttpRequest[ajaxId].status == 200) {
      var response = o2xmlHttpRequest[ajaxId].responseText.replace(/\+/g, " ");
      response     = unescape(response);
      var result;
      try {
        eval(response);
      }
      catch (e) {
        _ajaxAlert(getExceptionMessage(e) + "\nTried to eval:\n" + o2xmlHttpRequest[ajaxId].responseText, "o2XmlHttpRequest Error", "error");
        return;
      }
      if ( o2xmlHttpRequest[ajaxId].o2AjaxCallbackHandler ) { // doing this here to make sure that ajaxHandleServerResponse has it
        result.handler = o2xmlHttpRequest[ajaxId].o2AjaxCallbackHandler;
      }
      delete o2xmlHttpRequest[ajaxId]; // Very important that this line comes before ajaxHandleServerResponse(result)!
      ajaxHandleServerResponse(result);
    }
    else {
      if (document.location.href.indexOf("debug") != -1) {
        _ajaxAlert(o2xmlHttpRequest[ajaxId].statusText + "\n\n" + o2xmlHttpRequest[ajaxId].responseText, "There was a problem retrieving the XML data", "error");
      }
    }
    return result;
  }
}

function ajaxHandleServerResponseIframe(response) {
  ajaxHandleServerResponse(response);
}

function ajaxHandleServerResponse(result) {
  if (!result) {
    _ajaxRemoveClassNameActiveAjaxTarget( result.target );
    return;
  }
  if (result.debug == "1") {
    var debugString = "DEBUG:\n";
    for (var key in result) {
      debugString += key + " => " + result[key] + "\n";
    }
    _ajaxAlert(debugString);
  }
  if (result.result == "error") {
    _ajaxRemoveClassNameActiveAjaxTarget( result.target );
    if (result.onError == "ignore") {
      return;
    }
    if (result.onError && result.onError !== "undefined") {
      eval(result.onError);
    }
    else if (result.errorHandler && result.errorHandler !== "undefined") {
      eval(result.errorHandler + "(result);");
    }
    else if (result.errorMsg && result.onError !== "ignore") {
      _ajaxAlert(result.errorMsg, result.errorHeader, "error");
    }
    return;
  }
  if ((result.html && result.html != "undefined")   ||   (result.target && result.target != "undefined")) {
    var where   =   result.where   ?   result.where   :   "replace";
    ajaxUpdateContent({
      target              : result.target,
      content             : result.html,
      where               : where,
      ignoreMissingTarget : result.ignoreMissingTarget
    });
  }
  else if (result.target && result.target != "undefined" && result.where == "delete") {
    ajaxUpdateContent({
      target              : result.target,
      where               : "delete",
      ignoreMissingTarget : result.ignoreMissingTarget
    });
  }

  if (result.handler && result.handler != "undefined" && result.handler != "") {
    if( typeof(result.handler) === "function" ) {
      result.handler(result);
    }
    else {
      eval(result.handler + "(result);");
    }
  }

  if (result.onSuccess && result.onSuccess != "undefined") {
    eval(result.onSuccess);
  }
  if (result.javascriptFiles) {
    for (var i = 0; i < result.javascriptFiles.length; i++) {
      o2.require( result.javascriptFiles[i], function() { continueAjaxHandleServerResponse(result) } );
    }
  }
}

function continueAjaxHandleServerResponse(result) {
  if (result.continueAjaxHandleServerResponseDone) {
    return;
  }
  for (var i = 0; i < result.javascriptFiles.length; i++) {
    var url = result.javascriptFiles[i];
    if (!o2.hasBeenRequiredAndLoaded(url)) {
      return;
    }
  }
  result.continueAjaxHandleServerResponseDone = true;

  if (result.javascriptsToExecute) {
    for (var i = 0; i < result.javascriptsToExecute.length; i++) {
      eval( result.javascriptsToExecute[i] );
    }
  }
  if (result.cssFiles) {
    for (var i = 0; i < result.cssFiles.length; i++) {
      o2.require( result.cssFiles[i] );
    }
  }
  _ajaxRemoveClassNameActiveAjaxTarget( result.target );
}

function _ajaxRemoveClassNameActiveAjaxTarget(target) {  // Target elements should no longer have the className "activeAjaxTarget" (it's not active anymore)
  if (target) {
    var targets = _ajaxGetTargetsAsArray( target.toString() );
    for (var i = 0; i < targets.length; i++) {
      var elm = document.getElementById( targets[i] );
      if (elm) {
        o2.removeClassName(elm, "activeAjaxTarget");
      }
    }
  }
}

function _ajaxGetTargetsAsArray(targetStr) {
  if (!targetStr) {
    return new Array();
  }
  var targets = targetStr.split(",");
  for (var i = 0; i < targets.length; i++) {
    targets[i] = targets[i].replace(/^\s+/, "");
    targets[i] = targets[i].replace(/\s+$/, "");
  }
  return targets;
}

function ajaxUpdateContent(params) {
  var content = params.content;
  var where   = params.where;
  var ids = params.target.toString().split(",");
  for (var i = 0; i < ids.length; i++) {
    var target = ids[i].replace(/^\s+/, "");
    var elm = document.getElementById(target);
    if (!elm) {
      if (!params.ignoreMissingTarget) {
        alert("ajaxUpdateContent (ajax.js): Target element \"" + target + "\" does not exist");
      }
      continue;
    }
    if (where == "replace") {
      setInnerHtml(elm, content);
    }
    else if (where == "delete") {
      elm.parentNode.removeChild(elm);
    }
    else {
      addInnerHtml(elm, content, where);
    }
  }
  /*
    if (params.history == "store"
            || (params.where == "replace"   &&   params.history != "noStore")) {
        var id = params.target;
        o2ajaxHashVars[id] = params.content;
    }
  */
}

function ajaxCallIsInProgress(ajaxId) {
  return o2xmlHttpRequest[ajaxId] ? true : false;
}

function _ajaxAlert(msg, title, type) {
  // return alert(msg);
  if (!top.displayMessage) {
    if (navigator.appVersion.toLowerCase().match(/msie 6/)) {
      if (title) {
        msg = title + "\n\n" + msg;
      }
      return alert("Ajax Alert:" + msg);
    }
    var div = document.getElementById("ajaxMessageDiv");
    if (!div) {
      div = _createMessageDiv();
    }
    var html = "<pre>" + _encodeHtml(msg) + "</pre>";
    if (title) {
      html = "<h1>" + title + "</h1>" + html;
    }
    html += "<p><input type='button' value='OK' id='ajaxMessageDivCloseButton' onClick='document.getElementById(\"ajaxMessageDiv\").style.display = \"none\";'></p>";
    div.innerHTML = html;
    div.style.display = "";
    document.getElementById("ajaxMessageDivCloseButton").focus();
    div.scrollTop = 0;
    return;
  }
  if (type) {
    type = type.toLowerCase();
  }
  if (!type || type == "info") {
    top.displayMessage(msg);
  }
  else if (type == "error") {
    top.displayError(msg);
  }
}

function _createMessageDiv() {
  var div = document.createElement("div");
  div.id = "ajaxMessageDiv";
  document.body.appendChild(div);
  return div;
}

function _encodeHtml(html) {
  html = html.replace(/</g, "&lt;");
  html = html.replace(/>/g, "&gt;");
  return html;
}

