
// data_values[] is an array that contains the most recent values of
// physical devices. It is written either by writeDeviceVal(), called
// by the UDP monitor (when processing data broadcast by a logger, for
// local display), or  by setVals(), which is called by the XML processor 
// (when processing XML requested from the server - non-local mode).
//
// Also, the data_times[] array is maintained, as are last_data_values[]
// and last_data_times[], for the purpose of calculating rates of change.
// When data is coming directly from a logger, via udpApplet, the current
// browser time is used. When it is coming from server, the XML sent by
// the server contains the time.
//
// XML from the server comes enclosed with the tags VAL, TIME, LASTVAL, LASTTIME.
// Also sent are CAL_SCALE and CAL_OFFSET.
//
// The last_... arrays are just filled in with the previous values of
// time and value.
//

var DEBUG = false;
if(DEBUG)java.lang.System.out.println("debug mode");
function removeChildren(node){
    // remove all content
    while(node.hasChildNodes()) node.removeChild(node.childNodes[0]);
}

// Set the value in a text cell.

function setTD(thecell, value){
   removeChildren(thecell);
//java.lang.System.out.println("set " + thecell.id + " to " + value);
   var tnode = document.createTextNode(value);
   thecell.appendChild(tnode);
}

// This function returns the value of a device, given a deviceid. It
// simply looks up the value in the data_values associative array,
// which is indexed by the deviceid.

function getValue(deviceid){
   if(deviceid != undefined){ 
//java.lang.System.out.println("getValue() " + deviceid + " = " + data_values[deviceid] + " " + cal_scales[deviceid] + " " + cal_offsets[deviceid]);
      if(data_values[deviceid] == "NaN") return("--");
      return(data_values[deviceid]);
   }
}

function getAttr(deviceid, attrs){
   if(deviceid != undefined){
      return(attrs[deviceid]);
   }
}

function getDiff(deviceid, attrs1, attrs2){
//alert("getDiff " + deviceid);

   return((attrs1[deviceid] - attrs2[deviceid]) * cal_scales[deviceid]);
}

function getPollution(deviceid, attrs1, attrs2, attrsp){
//alert("getDiff " + deviceid);

   return(((attrs1[deviceid] - attrs2[deviceid]) * cal_scales[deviceid]) * attrsp[deviceid]);
}

// Calculate the rate of change of a variable.
function getRate(deviceid){
   if(deviceid != undefined){
      var val = data_values[deviceid];
      var time = data_times[deviceid];
      var last_val = last_data_values[deviceid];
      var last_time = last_data_times[deviceid];
      var rate = val - last_val / time - last_time;
      return(rate);
   }
}

function roundIt(value, digits){
   var factor = Math.pow(10, digits);
   return(Math.round(value * factor) / factor);
}

/** Get the value to be displayed, given the ID of the
 * element that displays it. This consults the display functions
 * array, which defines a function to be executed,  for each
 * displayable cell. 
 *
 * This function returns the calculated value.
 *
 */

function getDisplayValue(id){
   var thefunc = displayfuncs[id];

   if(thefunc != undefined){
//alert(id);

	if(DEBUG) java.lang.System.out.println(id + ": " + thefunc);
//alert(thefunc);
      var newval = eval(thefunc);
//alert(newval);
      current_display_vals[id] = newval;
      return(newval);
   }else{
	if(DEBUG) java.lang.System.out.println("function for " + id + " not defined");
   }
}

// Go through relevant cells in the displayed document
// and update what they are displaying.

function updateCellValues(){
   var elem;
   var allelems;
   var thisid;
   var cellval;
   var i;

//java.lang.System.out.println("updating cell values ");
   allelems = document.getElementsByTagName("TD");
   for(i = 0; i < allelems.length; i++){
      elem = allelems[i];
      thisid = elem.id; 
      if(thisid != undefined && thisid != ""){
         cellval = getDisplayValue(thisid);
	 current_val = elem.value;	
         if(cellval != undefined && cellval != current_val){
            if(isNaN(cellval) || cellval == undefined) cellval = "--";
//java.lang.System.out.println("updating TD " + thisid + " to " + cellval);
	    elem.value = cellval;
	    setTD(elem, cellval);
         }
      }
   }

   allelems = document.getElementsByTagName("SPAN");
   for(i = 0; i < allelems.length; i++){
      elem = allelems[i];
      thisid = elem.id; 
      if(thisid != undefined && thisid != ""){
         cellval = getDisplayValue(thisid);
	 current_val = elem.value;
         if(cellval != undefined && cellval != current_val){
            if(isNaN(cellval) || cellval == undefined) cellval = "--";
//java.lang.System.out.println("updating SPAN " + thisid + " to " + cellval);
	    elem.value = cellval;
	    setTD(elem, cellval);
         }
      }
   }

   // Get an array of all APPLETs
   allelems = document.getElementsByTagName("APPLET");
   // Go through them all
   for(i = 0; i < allelems.length; i++){
      elem = allelems[i];
      // get its ID
      thisid = elem.id;
      if(thisid != undefined && thisid != ""){
	 //current_val = elem.value;
         cellval = getDisplayValue(thisid);
if(DEBUG) java.lang.System.out.println("updating APPLET " + thisid + "  " + cellval);
         //if(cellval != undefined && cellval != current_val){
         if(cellval != undefined){
            if(cellval == "NaN" || isNaN(cellval)){ 
		cellval = "(no data available)";
	    }else{
  	        elem.value = cellval;
	    }
            elem.caption = cellval.toString();
	    //elem.repaint();
         }
      }	 
   }
}

// This function loads the XML document from the specified URL, and when
// it is fully loaded, passes that document and the url to the specified
// handler function.

var req;

function loadXML(loggerurl) {
//java.lang.System.out.println("loading xml - url = " + loggerurl);    
    var xmldoc;
    window.status = "Accessing Logger Data at " + loggerurl;
    // branch for native XMLHttpRequest object
    if (window.XMLHttpRequest) {
        req = new XMLHttpRequest();
        req.onreadystatechange = function(){
	                if(req.readyState == 4) setVals(req);};
        req.open("GET", loggerurl, true);
        req.send(null);
    }
    // Otherwise use Microsoft's proprietary API for Internet Explorer
    else if (window.ActiveXObject) { 
        req = new ActiveXObject("Microsoft.XMLHTTP");   // Create doc.
	if(req){
	     req.onreadystatechange = function(){
	                if(req.readyState == 4) setVals(req);}
	     req.open("GET", loggerurl, true);
	     req.send();
	}else{
	     alert("didn't create XMLHTTP object");
	}
    }else{
	alert("ActiveX objects not available.");
    }
}

// Called by the UDP applet to set the values of devices, as received
// from a logger broadcast.

function writeDeviceVal(deviceid, value){
if(DEBUG) java.lang.System.out.println("writeDeviceVal: set " + deviceid + " to " + value);
	var now = new Date();
	last_data_times[deviceid] = data_times[deviceid];
	data_times[deviceid] = Math.round(now.getTime() / 1000);
	last_data_values[deviceid] = data_values[deviceid];
	data_values[deviceid] = value;
}

// This one is called in response to having acquired XML giving values for a
// bunch of devices.

function setVals(req) {
//alert("setting vals from xml");
   if(req != undefined && req.responseXML != undefined){
    window.status = "Setting";
    //alert(req.responseText);
    var readers = req.responseXML.getElementsByTagName("RDR");
//java.lang.System.out.println("there are " + readers.length + " readers");
 	
     	// Loop through these reader elements
    for(var i = 0; i < readers.length; i++) {
         // For each employee, get name, job, and salary data using standard DOM
         // methods.  The name comes from an attribute.  The other values are
         // in Text nodes within <job> and <salary> tags.
         var e = readers[i];
 	var attrs = e.attributes;
 	if(attrs == undefined){
 		alert("attrs is undefined");
 	}else{
 		if(i == 0){
 			//alert(attrs[0].name + " " + attrs[0].value);
 		}
 		//alert("attrs has " + attrs.length + " elements");
 		var id = e.getAttribute("ID");
//java.lang.System.out.println(id + ": there are " + attrs.length + " attributes");
		for(var j = 0; j < attrs.length; j++){
			attr = attrs[j];
//alert(attr);
//java.lang.System.out.println("Load XML()-setVals() " + id + "  " + attr.name + " = " + attr.value);
			var attrname = attr.name;
			xml_tag_xref[attrname][id] = attr.value;
		}
 	}
   }
    updateCellValues();
   }
    window.status = "Done";
}