/**
 * Request handling Javascript functions used for the
 * EuroAlumni web application
 * (c) 2005 - 2008 Euro-Alumni e.V.
 **/

/** 
 * Request handler used to send XmlHttpRequests
 * to the server and give back the results
 **/
function RequestHandler() {

  /** The request used to contact the server */
  this.req = "";

  /** The server response as XML */
  this.serverXmlResponse = "";

  /** The server response as text */
  this.serverResponseText = "";

  /** The function to call when the xml response is available */
  this.functionToCallOnCompletion = function() {};
  
  /** Simple lock to prevent multiple execution */
  this.alreadySending = false;
  
  /** Internal cache buster **/
  this.cacheBuster = null;

  var _self = this;

  /**
   * Posts a GET request to the server, using an XMLHTTPRequest
   * Does not wait for the answer
   * @param pageName the name of the page to call
   * @param requestParamString the request parameters already assembled correctly
   *         (i.e. ?param1=foo&param2=bar)
   * @param completionFunction the actual function to call on 
   *         completion of the call (not just its name)
   */
  this.postGetRequest = function ( pageName, requestParamString, completionFunction ) {
    
    //Initialise the request
    this.initRequest( completionFunction );
    
    //If we got something, use it
    if( this.req ) {
  
      //Build the URL
      var urlToCall = pageName + requestParamString + this.cacheBuster;
  
      //From here on, IE works the same
      this.req.open( "GET", urlToCall, true );
      this.req.onreadystatechange = this.callback;
      this.req.setRequestHeader( "Content-Type", "text/xml; charset=utf-8" );
      this.req.setRequestHeader( "Accept-Charset", "UTF-8" );
      this.req.send( null );

      return;
    }
  
    //Does not support it, bail out here (silently!)
    return true;
  };
  
  
  /**
   * Posts a POST request to the server, using an XMLHTTPRequest
   * Does not wait for the answer
   * @param pageName the name of the page to call
   * @param requestParamString the request parameters already assembled correctly
   *         (i.e. ?param1=foo&param2=bar)
   * @param completionFunction the actual function to call on 
   *         completion of the call (not just its name)
   */
  this.postPostRequest = function ( pageName, requestParamString, completionFunction ) {
    
    //Initialise the request
    this.initRequest( completionFunction );
    
    //If we got something, use it
    if( this.req ) {
  
      //Build the URL
      var urlToCall = pageName + this.cacheBuster;

      //From here on, IE works the same
      this.req.open( "POST", urlToCall, true );
      this.req.onreadystatechange = this.callback;
      this.req.setRequestHeader( "Accept-Charset", "UTF-8" );
      this.req.setRequestHeader( "Content-Type", "application/x-www-form-urlencoded; charset=UTF-8" );
      this.req.send( requestParamString );
      
      return;
    }
  
    //Does not support it, bail out here (silently!)
    return true;
  };
  
  
  /**
   * Initialises the request and sets the completion function
   * @param completionFunction the actual function to call on 
   *         completion of the call (not just its name)
   */
  this.initRequest = function( completionFunction ) {
    
    //Exit if there is already a request
    if ( this.alreadySending === true ) {
      return;
    }
    
    //Lock it
    this.alreadySending = true;
    
    //Add cachebuster to the request parameter string
    this.cacheBuster = "&cb=" + ( new Date() ).getTime();
    
    //Record the function to call on completion
    this.functionToCallOnCompletion = completionFunction;
  
    //Get the correct thing and also do a very basic browser recognition
    if ( typeof XMLHttpRequest != 'undefined' ) {
  
      this.req = new XMLHttpRequest();
  
      // branch for IE/Windows ActiveX version
    } else if ( ! this.req ) {
  
      //Try to get first a newer, than an older IE version
      //of this object
      try {
        this.req = new ActiveXObject("Msxml2.XMLHTTP");
      } catch(e) {
        try {
            this.req = new ActiveXObject("Microsoft.XMLHTTP");
        } catch(e) {
            this.req = false;
        }
      }
    }
  }
  
  
  /**
   * Callback function gets called if the XmlHttpRequest object
   * changes its state (i.e. also when it is finished)
   */
  this.callback = function () {
  
    var requestHandler = _self;
  
    //Exit if req is not defined or null
    if ( (!requestHandler.req) || (requestHandler.req === null) ) {

      //Unlock            
      requestHandler.alreadySending = false;

      return;
    }
    
    //Check the result
    if (requestHandler.req.readyState == 4) {
       if (requestHandler.req.status == 200) {

          //Extract the content
          requestHandler.serverXmlResponse = requestHandler.req.responseXML;
          requestHandler.serverResponseText = requestHandler.req.responseText;
          
          //Call the defined function if it exists
          if ( (requestHandler.functionToCallOnCompletion !== null) && (requestHandler.functionToCallOnCompletion != "undefined") ) {
          
            //Call it
            setTimeout( function() { requestHandler.functionToCallOnCompletion(); }, 5 );
          }

          //Unlock            
          requestHandler.alreadySending = false;
       }
    }
    return;
  };
  
  
  /**
   * Returns a value from an xml node or an empty
   * string if the node cannot be found. The node is
   * searched in the supplied root node, the first text node
   * child of the first node with the correct name found 
   * is returned.
   * @param root the XML node in which to search
   * @param nodeName the name of the node to search for
   *        (that contains the text to return)
   * @return a String that contains the text or an empty
   *         String if nothing can be found
   **/
  this.getValueFromXmlNode = function ( root, nodeName ) {

    //Return an empty string if root or nodeName do not exist
    if ( !root || !nodeName || (root === null) || (nodeName === null) ) {
      return "";
    }
    
    //Get the node in question
    var nodesFound = root.getElementsByTagName( nodeName );
    if ( nodesFound.length > 0 ) {

      var nodeFound = nodesFound[0];
      if ( nodeFound && nodeFound.hasChildNodes() ) {

        var textNode = nodeFound.firstChild;
        if ( textNode && ( textNode !== null ) ) {
          return textNode.nodeValue;
        }
      }
    }
    
    //Return an empty string
    return "";
  };
  
  
  /**
   * Returns an xml node or null if the node cannot be found. 
   * The node is searched in the supplied root node.
   * @param root the XML node in which to search
   * @param nodeName the name of the node to search for
   * @return The node that contains the text or null
   *         if nothing can be found
   **/
  this.getXmlNode = function ( root, nodeName ) {

    //Return an empty string if root or nodeName do not exist
    if ( !root || !nodeName || (root === null) || (nodeName === null) ) {
      return null;
    }
    
    //Get the node in question
    var nodesFound = root.getElementsByTagName( nodeName );
    if ( nodesFound.length > 0 ) {

      var nodeFound = nodesFound[0];
      if ( nodeFound && ( nodeFound != null ) ) {

    	return nodeFound;
      }
    }
    
    //Return null
    return null;
  };  
}
