/***************************************************************
 *  I do not take credit for this script as it is not written  *
 *  by me. Instead, this script is taken from smoothping.com   *
 ***************************************************************/
 // multithreaded ping (should be, but not working, because of broken JS setTimeout)
var pingdisabled=0;
var maxpingtries=3; // max number of pings for each host
var delta=7; // delta ms - time for scripting/server overhead for 'pings'
var maxtimeout=4000; // 4 seconds for 1 ping
var serverlist=new Array();
var timeouts=new Array(); // timeout IDs
var starttimes=new Array(); // time when ping was started
var pingtries=new Array(); // countdown for each server starting from pingmaxtimes
var activecount=0; // how much hosts are still in progress of pinging
var pongs=new Array(); // pong reply time in ms
var accum=new Array(); // accumulated ping time
var flag_parallel=0; // 1 if parallell query, 0 - sequential
var accum_strategy=1; // ping accumulation strategy (not used):
                  // 0 - ignore first ping, show average
                  // 1 - show minimum
var fastestserver=-1;
var bestping=99999;

var now=0;

// accumulate ping replies 
function pongAccumulate(ip_idx) {
    if(ip_idx<0) ip_idx=activecount;
    if(accum[ip_idx]!=0){
          if((accum[ip_idx]+0)>(pongs[ip_idx]+0)) {
            accum[ip_idx]=pongs[ip_idx];
            if ((bestping+0)>(pongs[ip_idx]+0)){
              bestping=pongs[ip_idx];
              fastestserver=ip_idx;
            }
          }
    }
    else {
      accum[ip_idx]=pongs[ip_idx];
    }
}


// this function is called after the remote data is loaded
function p() {
    ip_idx=activecount;
    clearTimeout(timeouts[ip_idx]);
    timeouts[ip_idx]=0;
    var curr=new Date(); // local variable, bad for multithreading :-(
    now=curr.getTime();
    pongs[ip_idx]=((now-starttimes[ip_idx])-delta); 
    // normalize 'pong' - now it i a real ping time value
    pongAccumulate(ip_idx);
    dispatchnextping(ip_idx); // fields will be updated in dispatcher
}

function ping(ip_idx) {
    if(ip_idx<0) ip_idx=activecount;
    var proxy = new Ext.data.ScriptTagProxy({
       url:'http://'+serverlist[ip_idx]+'/pong.js',
       timeout: 6000 });
    var curr= new Date();
    starttimes[ip_idx] = curr.getTime();
//load( Object params, Ext.data.DataReader reader, Function callback, Object scope, Object arg )
    proxy.load('','',function (){ }, this);
    timeouts[ip_idx]=setTimeout('pingTimeoutCallback('+ip_idx+')',maxtimeout);
}

function pingTimeoutCallback(ip_idx) {
        if (timeouts[ip_idx]) {
          pongs[ip_idx]=-1; // that's a timeout flag
          // pongAccumulate(ip_idx, maxtimeout);
          clearTimeout(timeouts[ip_idx]);
          timeouts[ip_idx]=0;
          dispatchnextping(ip_idx); // fields will be updated in dispatcher
        }
}


function drawPingTimeout(ip_idx){
    if(ip_idx<0) ip_idx=activecount;
    document.getElementById(serverlist[ip_idx]).innerHTML='unavailable';
}

function drawPingValue(ip_idx, value){
    if(ip_idx<0) ip_idx=activecount;
    document.getElementById(serverlist[ip_idx]).innerHTML=value+' ms';
}

function drawStartAll() {
  document.getElementById('test').disabled=true;
}

// Stop processing all pings for given server - probably some screen update
function drawFinishOne(ip_idx) {

    var value='<span style="color: red">timeout</span>';
    if(ip_idx<0) ip_idx=activecount;
   // here some code to add, show mean value or change color, ...
    if (pongs[ip_idx]>0) 
    {
        value='<span>'+(accum[ip_idx]) + ' ms</span>';
    }
    document.getElementById(serverlist[ip_idx]).innerHTML=value;
}

function drawFinishAll() {
   // find the fastest server
  if (fastestserver>0) {
    value='<span class="best">'+(accum[fastestserver]) + ' ms</span>';
    document.getElementById(serverlist[fastestserver]).innerHTML=value;
  }
   document.getElementById('test').disabled=false;
}

// We come here either after ping reply or after ping timeout
function dispatchnextping(ip_idx) {
        if(ip_idx<0) ip_idx=activecount;
        // draw ping value or timeout
        if(pongs[ip_idx]<0) {
          drawPingTimeout(ip_idx);
          pingtries[ip_idx]=0; // stop pinging
        } else {
          drawPingValue(ip_idx, pongs[ip_idx]);
        }
        
	// check for this server is thats enough to ping?
        if (pingtries[ip_idx]>0) {
          pingtries[ip_idx]-=1;
          ping(ip_idx);
        } else {
          drawFinishOne(ip_idx);
          // Now the behaviour is different for parallel and serial call
          if(flag_parallel){ // parallel
            activecount-=1;  // that's a total count of unprocessed servers
            if (activecount<=0) {
              // stop all processing, enable PING button
              drawFinishAll();
            }
          } 
          else { // serial
            activecount+=1; // that' an index of active server
            if(activecount>=serverlist.length) {
              // stop all processing, enable PING button
              drawFinishAll();
              pingdisabled=0;
            }
            else {
              ping(activecount);
            }
          }
        }
}

function pingall(parallel, flag_accum) {
     if(parallel) flag_parallel=1;
     if(pingdisabled) return;
     pingdisabled=1;
     drawStartAll();
     activecount=serverlist.length;
     fastestserver=0;
     bestping=99999;
     // initialize variables
     for (var i = 0; i < activecount; i++){ 
       starttimes[i]=0;
       pongs[i]=0;
       timeouts[i]=0;
       accum[i]=0;
       pingtries[i]=maxpingtries;
       if (flag_parallel) { ping(i);}
     }
     if(!flag_parallel) { activecount=0; ping(activecount);}
}
