var jsrsContextPoolSize = 0;
var jsrsContextMaxPool = 10;
var jsrsContextPool = new Array();
var jsrsBrowser = jsrsBrowserSniff();
var jsrsElapsedTime=500;
var iCurrentHistory = history.length;
jsrsInit(1);

function jsrsInit(n)
{
	var contextObj;
	if(n >jsrsContextMaxPool) {
		alert("jsrsError: init over the max size");
		return;
	}
	for(; n>0; n--) {
		contextObj = jsrsContextPool[ jsrsGetContextID() ];
//		contextObj.busy=false;
		contextObj.setVisibility( false );
	}
	for(n=1; n<=jsrsContextPoolSize; n++) {
		contextObj = jsrsContextPool[ 'jsrs'+n ];
		contextObj.busy=false;
	}
	//alert(jsrsContextPoolSize);
}

// constructor for context object
function jsrsContextObj( contextID ){
  
  // properties
  this.id = contextID;
  this.busy = true;
  this.callback = null;
  this.container = contextCreateContainer( contextID );
  
  // methods
  this.callURL = contextCallURL;
  this.getPayload = contextGetPayload;
  this.setVisibility = contextSetVisibility;
}

//  method functions are not privately scoped 
//  because Netscape's debugger chokes on private functions
function contextCreateContainer( containerName ){
  // creates hidden container to receive server data 
  var container;
  switch( jsrsBrowser ) {
    case 'NS':
      container = new iLayer(100);
      container.name = containerName;
      container.visibility = 'hidden';
      container.clip.width = 100;
      container.clip.height = 100;
      break;
    
    case 'IE':
      document.body.insertAdjacentHTML( "afterBegin", '<span id="SPAN' + containerName + '"></span>' );
      var span = document.all( "SPAN" + containerName );
      var html = '<iframe name="' + containerName + '" src=""></iframe>';
      span.innerHTML = html;
      span.style.display = 'none';
      container = window.frames[ containerName ];
      break;
      
    case 'MOZ':  
    //alert("iframe");
      var span = document.createElement('SPAN');
      span.id = "SPAN" + containerName;
      document.body.appendChild( span );
      var iframe = document.createElement('IFRAME');
      iframe.name = containerName;
      span.appendChild( iframe );
      container = iframe;
      break;
  }
  return container;
}

function contextCallURL( URL ){
  switch( jsrsBrowser ) {
    case 'NS':
      this.container.src = URL;
      break;
    case 'IE':
      this.container.document.location.replace(URL);
      break;
    case 'MOZ':
      this.container.src = '';
      this.container.src = URL; 
      break;
  }  
}

function contextGetPayload(){
  switch( jsrsBrowser ) {
    case 'NS':
      return this.container.document.forms['jsrs_Form'].elements['jsrs_Payload'].value;
    case 'IE':
      return this.container.document.forms['jsrs_Form']['jsrs_Payload'].value;
    case 'MOZ':
      return window.frames[this.container.name].document.forms['jsrs_Form']['jsrs_Payload'].value; 
  }  
}

function contextSetVisibility( vis ){
  switch( jsrsBrowser ) {
    case 'NS':
      this.container.visibility = (vis)? 'show' : 'hidden';
      break;
    case 'IE':
      document.all("SPAN" + this.id ).style.display = (vis)? '' : 'none';
      break;
    case 'MOZ':
      document.getElementById("SPAN" + this.id).style.visibility = (vis)? 'show' : 'hidden';
      this.container.width = (vis)? 250 : 0;
      this.container.height = (vis)? 100 : 0;
      break;
  }  
}

function jsrsGetContextID(){
  var contextObj;
  for (var i = 1; i <= jsrsContextPoolSize; i++){
    contextObj = jsrsContextPool[ 'jsrs' + i ];
    if ( !contextObj.busy ){
      contextObj.busy = true;      
      return contextObj.id;
    }
  }
  // if we got here, there are no existing free contexts
  if ( jsrsContextPoolSize <= jsrsContextMaxPool ){
    // create new context
    var contextID = "jsrs" + (++jsrsContextPoolSize);
    jsrsContextPool[ contextID ] = new jsrsContextObj( contextID );
    return contextID;
  } else {
    alert( "jsrs Error:  context pool full" );
    return null;
  }
}

function jsrsPost( rspage,callback, parms, visibility ){
  // call a server routine from client code
  //
  // rspage      - href to asp file
  // callback    - function to call on return 
  //               or null if no return needed
  //               (passes returned string to callback)
  // parm        - object, pass a null or empty object if no data needed
  //               syntax { "name":"value", ... }
  // visibility  - optional boolean to make container visible for debugging
  //
  //  ***************** WARNING ***********************
  //	rspage MUST in the same domain.
  //
  // rspage content between BODY tag will be sent to the CallBack. If no BODY tag received then all 
  // data will be sent to the CallBack.
  iCurrentHistory = history.length;
  
  var contextObj = jsrsContextPool[ jsrsGetContextID() ];
  contextObj.callback = callback;
      
  var vis = (visibility == null)? false : visibility;
  contextObj.setVisibility( vis );

  //alert("in post "+contextObj.id );
  	container = window.frames[contextObj.id ]; // this works for ie and N6
  	//alert(container.document);
  	if(container.document==null)
  	{
  		// N6 is single threaded, document object won't be created unless you exit the current function
  		alert("jsrs Error: jsrsInit() not called, you have to call it for N6 only"); 
  		contextObj.busy=false;
  		return;
  	}	
  	container.document.clear();
  	// prepare post
  	var d=new Date();

  	var sPost='<HTML><BODY><FORM name="theForm" method="POST" Action="'+rspage+'">';
//  		"<INPUT TYPE=hidden Name=_hidden value="+d.getMilliseconds() +">"; // add a hidden element for N6 bug. if no param is sent: "container.document.theForm has no property"
  	if(parms!=null)
  	{
		for (key in parms)
		{
			// if type =TEXT, N6 will take a lot of CPU to render the page
			//sPost+='<SPAN>'+parms[key]+'</span>'; 

			sPost+='<INPUT TYPE=Hidden Name="'+key+'" size=40 value="'+parms[key]+'">'; 
			// Netscape 6.1+ bug, hidden type doesn't work, 601 works
		}
		
    	}
    	sPost+='<INPUT TYPE=submit></FORM></HTML></BODY>';
  	 //alert(sPost);
  	contextObj.sPost=sPost;
  	container.document.write(sPost);
  	//alert(sPost);
  	
  	// submit the form
  	container.document.theForm.submit();
  	//container.document.history.go(-1);
//  	contextObj.TimerID=window.setTimeout("jsrsSubmit('"+contextObj.id+"')",jsrsElapsedTime);
  	  	
  	// use timer to check load is complete or not
  	contextObj.TimerID=window.setTimeout("jsrsCheckLoaded('"+contextObj.id+"')",jsrsElapsedTime);
        	
	return contextObj.id;
}

function jsrsSubmit(contextID)
{
  	container = window.frames[contextObj.id ]; // this works for ie and N6
	//alert('before submit');
  	container.document.theForm.submit();
}

function jsrsCheckLoaded(contextID)
{
	contextObj=jsrsContextPool[contextID];
	window.clearTimeout(contextObj.TimerID); // clear timer
	// get iframe window
	var wIframe=window.frames[contextID];
	//alert(contextID+','+ wIframe);
	// check page loaded?
	var bLoaded=false;
	try{
	switch( jsrsBrowser ) {
    	case 'NS':// not suported 
    		break;
	case 'IE':
		if(wIframe.document.readyState == 'complete')
			bLoaded=true;
      		break;
    	case 'MOZ':
    		if(wIframe.document.body.innerHTML!=contextObj.sPost)
    			bLoaded=true;
    		break;
    	}
	} catch(e) {
		alert("jsrsError: The page you requested is not in the same domain."+e.message);	
		/*var s="";
		for (key in e)
		{
			s+=key+"="+e[key];
		}
		alert(s);*/
		contextObj.callURL("");
  		contextObj.busy=false;
		return;
	}
    	if(bLoaded) {
    		jsrsGetPostPayload(contextID);
    	} else { // check again
	  	contextObj.TimerID=window.setTimeout("jsrsCheckLoaded('"+contextObj.id+"')",jsrsElapsedTime);
    	}
   
}

function jsrsGetPostPayload(contextID)
{
	var wIframe = window.frames[contextID];
	
	//**strings**
	var sServerResults =    new String("");
		
    // get context object and invoke callback
    var contextObj = jsrsContextPool[ contextID ]; 
	
	sServerResults = wIframe.document.body.innerHTML.toString();	
	
	switch (jsrsBrowser ) 
	{
	    case 'IE':	
	    	/*
	    	var iSteps = iCurrentHistory - contextObj.container.history.length;
	    	
	    	contextObj.container.history.go(iSteps + 1);
	    	*/
	    	var iSteps = iCurrentHistory - top.history.length;
	    	
	    	if(iSteps>=0)
		    	iSteps=-2;
	    	contextObj.container.history.go(iSteps );
	    	break;
	    case 'MOZ':
	    	var iSteps = iCurrentHistory - window.frames[contextObj.container.name].history.length;
	    		    	
	    	wIframe.history.go(-1);
	    		    		    		    		    		    	
	    	break;	
	}
    
    if( contextObj.callback != null)
    {
        contextObj.callback(sServerResults, contextID);
    }
           
    // clean up and return context to pool
    contextObj.callback = null;
    contextObj.busy = false;
}

function jsrsExecute( rspage, callback, func, parms, visibility ){
  // call a server routine from client code
  //
  // rspage      - href to asp file
  // callback    - function to call on return 
  //               or null if no return needed
  //               (passes returned string to callback)
  // func        - sub or function name  to call
  // parm        - string parameter to function
  //               or array of string parameters if more than one
  // visibility  - optional boolean to make container visible for debugging
  
  // get context
  var contextObj = jsrsContextPool[ jsrsGetContextID() ];
  contextObj.callback = callback;

  var vis = (visibility == null)? false : visibility;
  contextObj.setVisibility( vis );

  // build URL to call
  var URL = rspage;

  // always send context
  URL += "?C=" + contextObj.id;

  // func and parms are optional
  if (func != null){
    URL += "&F=" + escape(func);

    if (parms != null){
      if (typeof(parms) == "string"){
        // single parameter
        URL += "&P0=[" + escape(parms+'') + "]";
      } else {
        // assume parms is array of strings
        for( var i=0; i < parms.length; i++ ){
          URL += "&P" + i + "=[" + escape(parms[i]+'') + "]";
        }
      } // parm type
    } // parms
  } // func

  // unique string to defeat cache
  var d = new Date();
  URL += "&U=" + d.getTime();

  // make the call
  contextObj.callURL( URL );
 
  return contextObj.id;
}

function jsrsLoaded( contextID ){
  // get context object and invoke callback
  var contextObj = jsrsContextPool[ contextID ];
  if( contextObj.callback != null){
    contextObj.callback( jsrsUnescape( contextObj.getPayload() ), contextID );
  }
  // clean up and return context to pool
  contextObj.callback = null;
  contextObj.busy = false;
}

function jsrsError( contextID, str ){
  //alert( unescape(str) );
  jsrsContextPool[ contextID ].busy = false
}

function jsrsUnescape( str ){
  // payload has slashes escaped with whacks
  return str.replace( /\\\//g, "/" );
}

function jsrsBrowserSniff(){
  if (document.layers) return "NS";
  if (document.all) return "IE";
  if (document.getElementById) return "MOZ";
  return "OTHER";
}

/////////////////////////////////////////////////
//
// user functions

function jsrsArrayFromString( s, delim ){
  // rebuild an array returned from server as string
  // optional delimiter defaults to ~
  var d = (delim == null)? '~' : delim;
  return s.split(d);
}

function jsrsDebugInfo(){
  // use for debugging by attaching to f1 (works with IE)
  // with onHelp = "return jsrsDebugInfo();" in the body tag
  var doc = window.open().document;
  doc.open;
  doc.write( 'Pool Size: ' + jsrsContextPoolSize + '<br><font face="arial" size="2"><b>' );
  for( var i in jsrsContextPool ){
    var contextObj = jsrsContextPool[i];
    doc.write( '<hr>' + contextObj.id + ' : ' + (contextObj.busy ? 'busy' : 'available') + '<br>');
    doc.write( contextObj.container.document.location.pathname + '<br>');
    doc.write( contextObj.container.document.location.search + '<br>');
    doc.write( '<table border="1"><tr><td>' + contextObj.container.document.body.innerHTML + '</td></tr></table>' );
  }
  doc.write('</table>');
  doc.close();
  return false;
}

function getService(sServerURL, sMethod, sCallBack, sReqMsg)
{
	if (typeof sReqMsg == "undefined") var sReqMsg = "";
	jsrsExecute(sServerURL, eval(sCallBack), sMethod, sReqMsg);	
}

function getCDF(rspage, callback, visibility)
{
	var contextObj = jsrsContextPool[jsrsGetContextID()];
	contextObj.callback = callback;
	var vis = (visibility == null)? false : visibility;
	contextObj.setVisibility(vis);
	contextObj.callURL(rspage);
  	sCDFContextID = contextObj.id; 
	return contextObj.id;
}

function cdfLoaded()
{
	var contextObj = jsrsContextPool[sCDFContextID];
//	alert("payload: " + contextObj.getPayload());  
	if (contextObj.callback != null)
		contextObj.callback(jsrsUnescape(contextObj.getPayload()), sCDFContextID);
		
	contextObj.callback = null;
	contextObj.busy = false;
}
 
