/*
 * Try - all arguments must be functions
 */
var _txId=0;

var Try = {
  these: function() {
    var returnValue;
    for (var i = 0; i < arguments.length; i++) {
      var lambda = arguments[i];
      try {
        returnValue = lambda();
        break;
      } catch (e) {}
    }
    return returnValue;
  }
};

Object.extend = function(destination, source) {
  for (property in source) {
    destination[property] = source[property];
  }
  return destination;
};


var Query =
{
  getTransport: function() 
  {
    return Try.these(
      function() {return new ActiveXObject('Msxml2.XMLHTTP')},
      function() {return new ActiveXObject('Microsoft.XMLHTTP')},
      function() {return new XMLHttpRequest()}
    ) || false;
  },

/*
	fnCallback is called when ready state is complete
*/

  request: function(path,fnCallback,params,lparam)
  {
  	var _transID = 'ajax'+_txId++;
  	
  	Query.transport[_transID] = Query.getTransport();
	if(!Query.transport[_transID]) return null;

	Query.states[_transID]=null;
	Query.params[_transID]=params;
	Query.reqdata[_transID]={p:path,f:fnCallback,r:params,l:lparam};

	Query.transport[_transID].onreadystatechange = function()
	{
		Query.states[_transID] = Query.transport[_transID].readyState;
		
		if( Query.transport[_transID].readyState==Query.RS_COMPLETE )
		{
			if( Query.transport[_transID].status == 200 )
			{
				fnCallback(Query.transport[_transID].responseXML,lparam,Query.params[_transID]);

				Query.transport[_transID] = null;
				Query.params[_transID] = null;
				Query.states[_transID] = null;
				Query.reqdata[_transID] = null;
			}
			else if( Query.transport[_transID].status >= 12000 )
			{
				switch(Query.transport[_transID].status){
				// The following case labels are wininet.dll error codes that may be encountered.
				// Server timeout
				case 12002:
				// 12029 to 12031 correspond to dropped connections.
				case 12029:
				case 12030:
				case 12031:
				// Connection closed by server.
				case 12152:
				// See above comments for variable status.
				case 13030:
					// let's retry
					Query.request( Query.reqdata[_transID].p, Query.reqdata[_transID].f, Query.reqdata[_transID].r, Query.reqdata[_transID].l );
					Query.transport[_transID] = null;
					Query.params[_transID] = null;
					Query.states[_transID] = null;
					Query.reqdata[_transID] = null;
				}
			}
			else if( Query.transport[_transID].status >= 400 )
			{
				Messages.mbOk("Request failed: "+Query.transport[_transID].status,'error');

				Query.transport[_transID] = null;
				Query.params[_transID] = null;
				Query.states[_transID] = null;
				Query.reqdata[_transID] = null;
			}
		}
	};

	var query = '';
	var c=0;
	for( var k in params )
	{
		if( c++>0 ) query += '&';
		query += k+'=';

		if( is_array(params[k]) )
		{
			for( var l=0; l<params[k].length; l++ )
			{
				if( l++>0 ) query += ',';
				query += escape(params[k][l]);
			}
		}
		else
		{
			query += escape(params[k]);
		}
	}

	Query.transport[_transID].open('POST', Session.vdir+Query.querydir+'/'+path, true );
	Query.transport[_transID].setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
	Query.transport[_transID].send(query);

//	if( params['action']=='saveObject' ) {
//		Debug.add(query);
//	}
	
	return true;
  },

  /* send data - don't care about checking response */

  sendData: function(path,params)
  {
  	var _transID = 'ajax'+_txId++;
  	Query.transport[_transID] = Query.getTransport();
	if(!Query.transport[_transID]) return null;
	Query.transport[_transID].onreadystatechange = function()
	{
		if( Query.transport[_transID].readyState==Query.RS_COMPLETE )
		{
			if( Query.transport[_transID].status == 200 )
			{
				Query.transport[_transID] = null;
			}
			else if( Query.transport[_transID].status >= 400 )
			{
				Messages.mbOk("SendData failed: "+Query.transport[_transID].status,'error' );
				Query.transport[_transID] = null;
			}
		}
	};
	var query = '';
	var c=0;
	for( var k in params )
	{
		if( c++>0 ) query += '&';
		query += k+'='+escape(params[k]);
	}

	Query.transport[_transID].open('POST', Session.vdir+Query.querydir+'/'+path, true );
	Query.transport[_transID].setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
	Query.transport[_transID].send(query);
	return true;
  },
  transport: new Array(),
  params: new Array(),
  states: new Array(),
  reqdata: new Array(),
  querydir: '/query',
  RS_INIT:	0,
  RS_LOADING: 1,
  RS_LOADED: 2,
  RS_INTERACTIVE: 3,
  RS_COMPLETE: 4
}

