/*
 * File         : ajax.js
 * Created      : 2007, Extended 20091003
 * Author       : JT Best
 * Organisation : OpenPoplog Association
 * Copyright    : (c) 2007-10, OpenPoplog Association
 * Purpose      : Implement a Javascript AJAX object to use with DOM.
 * Dependencies : dom.js        [Mandatory] OPWC DOM Abstraction Layer
 * To Do        : 
 * Design       : AJAX supports utility methods for association target elements with asynchronously fetched content.
 * Changes      :
 */

AJAX = function () {
  this.strStatusMessage = "";
  //this.objHTTPRequest = this.createHTTPRequestObject();
  this.onReadyStateChange = this.ONREADYSTATECHANGE;
  this.arrOnReadyStateHandlers = [ false, false, false, false, this.onRequestComplete ];
  this.intReadyState = 0;
  this.intStatus = 0;
  this.strResponse = "";
  this.strMimeType = "";
  this.strTarget = "";
  this.objTarget = null;
  this.objInjectedElement = null;
};

AJAX.prototype.associateReadyStateHandlers = function ( varHandlers ) {
  switch ( varHandlers.constructor ) {
    case Function:
      this.onReadyStateChange = varHandlers;
      break;
    case Object:
      if ( varHandlers.onReadyStateChange )this.onReadyStateChange = varHandlers.onReadyStateChange;
      if ( varHandlers.ReadyState0 ) this.arrOnReadyStateHandlers[ 0 ] = varHandlers.ReadyState0;
      if ( varHandlers.ReadyState1 ) this.arrOnReadyStateHandlers[ 1 ] = varHandlers.ReadyState1;
      if ( varHandlers.ReadyState2 ) this.arrOnReadyStateHandlers[ 2 ] = varHandlers.ReadyState2;
      if ( varHandlers.ReadyState3 ) this.arrOnReadyStateHandlers[ 3 ] = varHandlers.ReadyState3;
      if ( varHandlers.ReadyState4 ) this.arrOnReadyStateHandlers[ 4 ] = varHandlers.ReadyState4;
      break;
  }
};

AJAX.prototype.createHTTPRequestObject = function () {
  var objHttpRequest;
  try {
    objHttpRequest = new XMLHttpRequest();
  }
  catch ( excOuter ) {
    var arrXmlHttpVersions = [ 'MSXML2.XMLHTTP.8.0', 
                               'MSXML2.XMLHTTP.7.0', 
                               'MSXML2.XMLHTTP.6.0', 
                               'MSXML2.XMLHTTP.5.0',
                               'MSXML2.XMLHTTP.4.0',
                               'MSXML2.XMLHTTP',
                               'Microsoft.XMLHTTP' ];
    for ( var intIndex = 0; intIndex < arrXmlHttpVersions.length && !objHttpRequest; intIndex++ ) {
      try {
        objHttpRequest = new ActiveXObject( arrXmlHttpVersions[ intIndex ] );
      }
      catch ( excInner ) { } // Ignore any exceptions.
    }
  }
  if ( !objHttpRequest ) {
    this.strStatusMessage = "Could not create XML HTTP Object\n"; // + e.toString();
  }
  objHttpRequest.AJAX = this;
  return objHttpRequest;
};

AJAX.prototype.injectContent = function ( varContent, varTarget, strElementType ) {
  if ( varContent && varTarget ) {
    this.objTarget = dom.getObject( varTarget );
    if ( strElementType ) {
      this.objInjectedElement = dom.createElement( this.objTarget, strElementType, false, varContent );
    } else {
      dom.appendContent( this.objTarget, varContent );
    }
  }
};

AJAX.prototype.issueRequest = function ( strMethod, strURL, blnAsynchronous, 
                                         strUser, strPassword, fnHandlers, 
                                         strDataToSend, objCompletionAttributes
                                       ) {
  if ( !this.objHTTPRequest ) {
    this.objHTTPRequest = this.createHTTPRequestObject();
  }
  if ( this.objHTTPRequest ) {
    // Sanity check the arguments
    if ( !strMethod || !(strMethod == 'GET' || strMethod == 'POST' ) ) { strMethod = 'GET'; }
    try {
      this.objCompletionAttributes = objCompletionAttributes;
      if ( strUser ) {
        this.objHTTPRequest.open( strMethod, strURL, blnAsynchronous, strUser, strPassword );
      } else {
        this.objHTTPRequest.open( strMethod, strURL, blnAsynchronous );
      }
      if ( fnHandlers ) {
        if ( fnHandlers != {} ) this.associateReadyStateHandlers( fnHandlers );
      }
      this.objHTTPRequest.onreadystatechange = this.onReadyStateChange;
      if ( strDataToSend ) 
        this.objHTTPRequest.send ( strDataToSend )
      else 
        this.objHTTPRequest.send ( "" );
    }
    catch ( e ) {
      this.strStatusMessage = "Cannot connect to server:\n" + e.toString();
      this.objHTTPRequest.abort();
    }
  }
};

AJAX.prototype.loadCSS = function ( strTarget, strURL, strUser, strPassword ) {
  
};

AJAX.prototype.loadJavascript = function ( strTarget, strURL, strUser, strPassword ) {
  
};

AJAX.prototype.loadText = function( strTarget, strMethod, strURL, blnAsynchronous, 
                                    strUser, strPassword, 
                                    strDataToSend, strMimeType, objCompletionAttributes
                                  ) {
  this.strTarget = strTarget;
  if ( strMimeType ) this.strMimeType = strMimeType;
  this.issueRequest( strMethod, strURL, blnAsynchronous, strUser, strPassword, false, strDataToSend, objCompletionAttributes );
};

AJAX.prototype.onRequestComplete = function () {
  // Context is AJAX object
  if ( this.strResponseText ) {
    // Check for server error
    if ( this.strResponseText.indexOf( "ERRNO" ) >= 0 || this.strResponseText.indexOf( "error:" ) >= 0 || this.strResponseText.length == 0 ) {
      this.strStatusMessage = (this.strResponseText.length == 0) ? "Server error." : this.strResponseText;
    } else {
      if ( this.strMimeType ) {
        switch ( this.strMimeType.toLowerCase() ) {
          case "application/javascript":
            break;
          case "image/png":
            break;
          case "multipart/mixed":
            break;
          case "text/css":
            break;
          case "text/html":
            this.injectContent( this.responseText, this.strTarget, false );
            break;
          case "text/javascript":
            break;
          case "text/plain":
            break;
          case "text/xml":
            break;
          default:
            this.injectContent( this.strResponseText, this.strTarget, false );
            break;
        }
      } else {
        this.injectContent( this.strResponseText, this.strTarget, false );
      }
      var objTarget = dom.getObject( this.strTarget );
      if ( objTarget && this.objCompletionAttributes ) {
        for ( var strKey in this.objCompletionAttributes ) {
          var varValue = this.objCompletionAttributes[ strKey ];
          objTarget.setAttribute( strKey, varValue );
        }
      }
    }
  }
  delete this.objHTTPRequest;
};

AJAX.prototype.ONREADYSTATECHANGE = function () {
  // Context is XmlHttpRequest object
  if ( this.AJAX ) {
    var objAJAX = this.AJAX;
    objAJAX.intReadyState = this.readyState;
    if ( this.status ) objAJAX.intStatus = this.status;
    objAJAX.fnReadyState = objAJAX.arrOnReadyStateHandlers[ this.readyState ];
    
    switch ( this.readyState ) {
      case 0:  // Uninitialised
        if ( objAJAX.fnReadyState ) {
          objAJAX.fnReadyState();
        }
        break;
      case 1:  // Loading
        if ( objAJAX.fnReadyState ) {
          objAJAX.fnReadyState();
        }
        break;
      case 2:  // Loaded
        if ( objAJAX.fnReadyState ) {
          objAJAX.fnReadyState();
        }
        break;
      case 3:  // Interactive
        if ( objAJAX.fnReadyState ) {
          objAJAX.fnReadyState();
        }
        break;
      case 4:  // Complete
        if ( this.status >= 200 && this.status <= 299 ) {
          objAJAX.strResponseText = this.responseText;
          if ( objAJAX.fnReadyState ) {
            objAJAX.fnReadyState();
          }
        }
        break;
    }
  }
};

AJAX.prototype.processAttributes = function ( v_objAttributes ) {
  if ( !v_objAttributes ) {
    
  } else {
    if ( v_objAttributes.ASYNCHRONOUS ) this.blnAsynchronous = v_objAttributes.ASYNCHRONOUS;
    if ( v_objAttributes.COMPLETION )   this.blnAsynchronous = v_objAttributes.COMPLETION;
    if ( v_objAttributes.DATATOSEND )   this.strDataToSend = v_objAttributes.DATATOSEND;
    if ( v_objAttributes.METHOD )       this.strMethod = v_objAttributes.METHOD;
    if ( v_objAttributes.MIMETYPE )     this.strMimeType = v_objAttributes.MIMETYPE;
    if ( v_objAttributes.PASSWORD )     this.strPassword = v_objAttributes.PASSWORD;
    if ( v_objAttributes.TARGET )       this.strTarget = v_objAttributes.TARGET;
    if ( v_objAttributes.URL )          this.strURL = v_objAttributes.URL;
    if ( v_objAttributes.USER )         this.strUser = v_objAttributes.USER;
  }
};

