// Global variables
// Unique request id
var gRequestId = 0;
// If we are waiting for a request to respond
var gWaiting = false;
// The id of the request we are waiting for
var gWaitingForRequestId = null;
// The time the request we are waiting for was sent
var gWaitingForRequestSent = null;
// Id of a timedout request, if it returns later than timeout it is blocked
var gTimedOutRequests = new Array();

var gLoadingRequests = new Array();

var gDebug = false;

/****
 * Creates a ajax object and sends a request to the server
 * @author Ola Juliussen
 * @version 1.00 09.10.2006
 * @param string  pUrl request url
 * @param string  pParameters request parameters in format var_name=var_value&var_name2=var_value2&......
 * @param bool    pWait       if true this will block all other "wait" requests until it has returned
 * @param string  pMethod     optional, can be POST or GET, default POST
 */
function request( pUrl, pParameters, pWait, pMethod )
{        
  hideLoading();
  
  if( !pMethod )
    pMethod = 'POST';
    
  // Return if pWait is true and gWaiting is true unless the request we are waiting for
  // has timedout, because we are waiting already
  if( pWait == true && gWaiting == true )
  {
    if( ( new Date().getTime() - gWaitingForRequestSent ) > 60000)
      gTimedOutRequests.push( gWaitingForRequestId );
    else
	  return;
  }

  var loRequestId = gRequestId++;

  if( pWait == true )
  {
    gWaiting = true;
    gWaitingForRequestId = loRequestId;
    gWaitingForRequestSent = new Date().getTime();
  }

  try
  {
    var loAjax = new Ajax( pWait, loRequestId );
    loAjax.sendRequest( pUrl, pParameters, pMethod );    
    gLoadingRequests.push( loRequestId );    
    delete loAjax;
  }
  catch( loError )
  {
    //alert( 'Det oppstod en feil ved sending av forespørsel til server' );
  }
}
/****
 * Ajax class
 * @author Ola Juliussen
 * @version 1.00 09.10.2006
 * @param bool    pWait       if true this will block all other "wait" requests
 */
function Ajax( pWait, pRequestId )
{
  this.mComObject = null;
  this.mWait = pWait;
  this.mRequestId = pRequestId;

  /****
   * Sends a request to the server
   * @author Ola Juliussen
   * @version 1.00 09.10.2006
   * @param string pUrl request url if GET parameters is in this variable
   * @param string pParameters request parameters only used when POST in format var_name=var_value&var_name2=var_value2&......
   * @param string pMethod must be POST or GET
   */
  this.sendRequest = function( pUrl, pParameters, pMethod )
  {             
    // Get ajax communication object
    this.mComObject = this.getComObject();
    if( this.mComObject )
    {
      try
      {
        // Response function
        var loAjax = this;
        this.mComObject.onreadystatechange = function(){ loAjax.handleResponse(); }
        // The request
        
        // If GET request add parameters to url
        if( pMethod = 'GET' )
          pUrl += '?' + pParameters;
        
        this.mComObject.open( pMethod, pUrl, true );
        // If POST add headers
        if( pMethod.toUpperCase() == 'POST' )
        {
          this.mComObject.setRequestHeader( 'Content-Type', 'application/x-www-form-urlencoded' );
          if( pParameters )
            this.mComObject.setRequestHeader( 'Content-length', pParameters.length );
          this.mComObject.setRequestHeader( 'Connection', 'close' );
        }
        // Send the request with parameters, pParameters is null if GET
        this.mComObject.send( pParameters );
      }
      catch( loError )
      {
        //alert( 'Det oppstod en feil ved sending av forespørsel tilserver' );
      }
    }
    else
    {
      //alert( 'Nettleseren din støtter ikke ajax' );
    }
  }
  /****
   * Handles the server response
   * @author Ola Juliussen
   * @version 1.00 09.10.2006
   */
  this.handleResponse = function()
  {
    // Check for readyState, if 4 the response is available
    if( this.mComObject.readyState == 4 )
    {
      // Check if this request has timed out, if so remove it from list of timedout requests and return
      if( gTimedOutRequests.indexOf( this.mRequestId ) != -1 )
      {
        gTimedOutRequests.removeByValue( this.mRequestId );
        gLoadingRequests.removeByValue( this.mRequestId );
        return;
      }

      // Check for http status, 200 is OK
      if( this.mComObject.status == 200 )
      {
        try
        {
          // Get server response, get both xml document and the response in text format

		  if( gDebug )
		    alert( this.mComObject.responseText );

          var loResponse = eval( '(' + this.mComObject.responseText + ')' );

          for( var i = 0; i < loResponse.length; i++ )
          {
            switch( loResponse[ i ].mType )
            {									         
              case 'change_content'      : document.getElementById( loResponse[ i ].mTarget ).innerHTML = loResponse[ i ].mContent;
                                           break;
              case 'add_content'         : document.getElementById( loResponse[ i ].mTarget ).innerHTML += loResponse[ i ].mContent;
                                           break;
              case 'change_value'        : document.getElementById( loResponse[ i ].mTarget ).value = loResponse[ i ].mValue;
                                           break;
              case 'add_value'           : document.getElementById( loResponse[ i ].mTarget ).value += loResponse[ i ].mValue;
                                           break;
              case 'set_focus'           : document.getElementById( loResponse[ i ].mTarget ).focus();
                                           break;
              case 'set_select'          : document.getElementById( loResponse[ i ].mTarget ).select();
                                           break;
              case 'change_class'        : document.getElementById( loResponse[ i ].mTarget ).className = loResponse[ i ].mClass;
                                           break;
              case 'add_class'           : document.getElementById( loResponse[ i ].mTarget ).className += ' ' + loResponse[ i ].mClass;
                                           break;
              case 'alert'               : alert( loResponse[ i ].mMessage );
                                           break;
              case 'javascript'          : eval( loResponse[ i ].mCode );
                                           break;
              default                    : //alert( 'Ukjent svar fra server' );
                                           break;
            }
          }
        }
        catch( loError )
        {
	  		//alert( 'Feil ved svar returnert av server: ' + loError.message );
	  	  //alert( 'Feil ved svar returnert av server: ' + loError.message + ' feil: ' +this.mComObject.responseText);
        }
      }
      else
      {
        switch( this.mComObject.status )
        {
          case 403 : //alert( 'Du har ikke tilgang til forespurte data' );
                     break;
          case 404 : //alert( 'Forespurte data finnes ikke' );
                     break;
          default  : //alert( 'Feil: ' + this.mComObject.status );
                     break;
        }
      }
      // Clean up

      // If this request was a wait request, tell the system that its finished loading
      // and we can handle new requests
      if( this.mWait == true )
      {
        gWaitingForRequestId = null;
        gWaitingForRequestSent = null;
        gWaiting = false;
      }
            
	  gLoadingRequests.removeByValue( this.mRequestId );

      delete this.mComObject;
    }
  }
  /****
   * Creates the object used for communication with the server
   * @author Ola Juliussen
   * @version 1.00 09.10.2006
   * @return object|null returns ajax communication object if browser supports ajax else null
   */
  this.getComObject = function()
  {
    // Local ajax communication object
    var loComObject;
    try
    {
      // Internet Explorer newer versions
      loComObject = new ActiveXObject( 'Msxml2.XMLHTTP' ) ;
    }
    catch( loError )
    {
      try
      {
        // Internet Explorer
        loComObject = new ActiveXObject( 'Microsoft.XMLHTTP' );
      }
      catch( loError )
      {
        try
        {
          // Others -> FireFox, Opera etc
          loComObject = new XMLHttpRequest();
        }
        catch( loError )
        {
          // Browser don't support Ajax
          loComObject = null;
        }
      }
    }
    // Return ajax communication object or null
    return loComObject;
  }
}


/**
 * Array function, checks if a value is in the array
 *
 * @author Ola Juliussen
 * @version 1.00 06.11.2006
 * @param object      pValue   the object to check for
 */
Array.prototype.indexOf = function( pValue )
{
  var loLength = this.length;
  for( var i = 0; i < loLength; i++ )
    if( this[ i ] == pValue )
      return i;
  return -1;
}
/**
 * Array function, remove all elements with value like pValue
 *
 * @author Ola Juliussen
 * @version 1.00 06.11.2006
 * @param object      pValue   the object to remove
 */
Array.prototype.removeByValue = function( pValue )
{
  var loLength = this.length;
  var j = 0;
  var loRemovedElements = 0;
  for( var i = 0; i < loLength; i++ )
    if( this[ i ] != pValue )
      this[ j++ ] = this[ i ];
    else
      loRemovedElements++;
  this.length -= loRemovedElements;
}
/**
 * Urlencodes a string
 *
 * @author Ola Juliussen
 * @version 1.00 31.10.2006
 * @param string pString   the string to urlencode
 * return string           a urlencoded string
 */
function urlEncode( pString )
{
  return escape( pString ).replace( /[+]/g, '%2B' );
}
function isDefined( pObject )
{
  if( typeof( pObject ) == 'undefined' )
    return false;
  else
    return true;
}
function isNumber( pObject )
{
  if( isNaN( pObject ) || typeof( pObject ) != 'number' )
    return false;
  else
    return true;
}
function isString( pObject )
{
  if( typeof( pObject ) != 'string' )
    return false;
  else
    return true;
}
function setLeft( pElement, pValue )
{
  if( isString( pElement.style.left ) )
  {
    if( isNumber( pValue ) )
      pElement.style.left = pValue + 'px';
    else
      pElement.style.left = '0px';
  }
  else if( isDefined( pElement.style.pixelLeft ) )
  {
    if( isNumber( pValue ) )
      pElement.style.pixelLeft = pValue;
    else
      pElement.style.pixelLeft = 0;
  }
  return;
}
function setTop( pElement, pValue )
{
  if( isString( pElement.style.top ) )
  {
    if( isNumber( pValue ) )
      pElement.style.top = pValue + 'px';
    else
      pElement.style.top = '0px';
  }
  else if( isDefined( pElement.style.pixelTop ) )
  {
    if( isNumber( pValue ) )
      pElement.style.pixelTop = pValue;
    else
      pElement.style.pixelTop = 0;
  }
  return;
}
function getHeight( pElement )
{
  if( isDefined( pElement.offsetHeight ) && isString( pElement.style.height ) )
    return pElement.offsetHeight;
  else if( isDefined( pElement.style.pixelHeight ) )
    return pElement.style.pixelHeight;
}
function getWidth( pElement )
{
  if( isDefined( pElement.offsetWidth ) && isString( pElement.style.width ) )
    return pElement.offsetWidth;
  else if( isDefined( pElement.style.pixelWidth ) )
    return pElement.style.pixelWidth;
}
function getPageY( pElement )
{
  var loY = 0;
  while( pElement )
  {
    if( isDefined( pElement.offsetTop ) )
      loY += pElement.offsetTop;
    pElement = isDefined( pElement.offsetParent ) ? pElement.offsetParent : null;
  }
  return loY;
}
function getPageX( pElement )
{
  var loX = 0;
  while( pElement )
  {
    if( isDefined( pElement.offsetLeft ) )
      loX += pElement.offsetLeft;
    pElement = isDefined( pElement.offsetParent ) ? pElement.offsetParent : null;
  }
  return loX;
}

function setLoading( pElementId )
{
  if( !document.getElementById( pElementId ) )
    return;
  
  var loElement = document.getElementById( pElementId );
  var loHeight = getHeight( loElement );
  var loWidth = getWidth( loElement );  
  var loTop = getPageY( loElement );
  var loLeft = getPageX( loElement );  
  
  if( !document.getElementById( 'loading' ) )
    return;  
    
  var loLoadingElement = document.getElementById( 'loading' );
  
  
  setLeft( loLoadingElement, loLeft );
  setTop( loLoadingElement, loTop );
  loLoadingElement.style.height= loHeight;
  loLoadingElement.style.width= loWidth;
  loLoadingElement.style.display='block';  
}

function hideLoading()
{
  if( !document.getElementById( 'loading' ) )
    return;  

  var loLoadingElement = document.getElementById( 'loading' );
  loLoadingElement.style.display='none';  
}

