/*
$HeadURL: file:///svn/CHjPS/trunk/CHjPS/js/tracer.js $   
 $Author: francis $
    $Rev: 13 $   
   $Date: 2011-01-13 04:35:33 +0100 (Thu, 13 Jan 2011) $ */ 

/* =================================================================== */
/* Provides trace classes/filtering with timestemp over                */
/* console.log (firebug)                                               */
/* =================================================================== */

var traceError        = 0;  // Serious logic flaws, effectively assert()
var traceWarning      = 1;  // Warning that are not error, like server not responding
var traceInfo         = 2;  // information like screen size, layout decisions
var traceReady        = 3;  // Feel good startup traces
var traceDebug        = 4;  // Whatever being actively debugged
var traceAjax         = 5;  // I'm not here yet but probably going to be important
var traceTimerExpire  = 6;  // timers expiring are rare enough, and interesting
                              //   traces from here frequent and normally disabled.
var traceState        = 7;  // Very important if state machine broken
var traceEvent        = 8;  // Non timer, mouse, keyboard events
var traceKeystroke    = 9;  // Whatever the user types
var traceMouse        = 10; // You'll see a lot of mouse on/offs
var traceTimer        = 11; // and even more started and immedietly stopped timers
var traceCss          = 12; // Patches to DOM
var traceHtml         = 13; // This one can be a very long trace

var traceResize       = 14; // The first non "standard" trace

var levelText         = Array( "Error", "Warning", "Info",    "Ready", "Debug", "Ajax", "Expire",
                                 "State", "Event",   "Keystrk", "Mouse", "Timer", "Css",  "Html",
                                 "Resize" );
var   traceEnable       = Array(  false,   false,     false,     false,   false,   false,  false,
                                  false,   false,     false,     false,   false,   false,  false,
                                  false );
var   traceDefault      = Array(  true,    true,      true,      true,    true,    true,   true,
                                  true,    true,      true,      false,   false,   true,   false,
                                  true );
var   firstTrace        = true;
var   consoleFound      = true;
var   traceTime         = null;

/* This procedure should be called before any tracing. Accepts a trace enable mask
   or uses default if null. Probes console.log to make sure it exists. If trace
   is called before traceInit, and firebug is not installed, a runtime JS error 
   occurrs. Reports which traces are enabled. */
/* =================================================================== */
function traceInit( enable ) {
  var t;
  if (enable == null)
    traceEnable = traceDefault;
  else
    for (i=0; i<enable.length; i++)
      traceEnable[i] = enable[i];

  t = '';
  for (i=0; i<traceEnable.length; i++)
    if ( traceEnable[i] )
      t+= levelText[i]+' ';
  if (t.length > 0)
    probeTrace( 'Traces  enabled = '+t );

  t = '';
  for (i=0; i<traceEnable.length; i++)
    if ( !traceEnable[i] )
      t+= levelText[i]+' ';
  if (t.length > 0)
    probeTrace( 'Traces disabled = '+t );
}
/* Generates a time stamp relative to the previous trace. The first trace
   reports the current time in 24h format 99:99. 
   If the previous trace was less than 10s back, then reported as 9.999 
   giving 0.001s accuracy. If between 10 and 1000s reported as 999.9 giving
   0.1s accuracy. If between 1000s and 1 day reported as 99999 for 1s
   accuracy. If longer than 1 day ----- to show overflow.
/* =================================================================== */
function timeStamp() {
  var msDay = 86400000;
  var   t     = '';
  var   time  = new Date();

  if (traceTime == null) {
    var mins  = time.getMinutes();
    var hours = time.getHours();
    if (hours<10)
      t = '0';
    t += hours+':';
    if (mins<10)
      t += '0';
    t += mins;
  } else {
    var elapsed = time.getTime() - traceTime.getTime();
    if (elapsed >= msDay)
      t = '-----';
    else {
      secs = parseInt( elapsed / 1000 );
      ms   = elapsed - secs * 1000;
      if (secs < 10) {
        t = secs+'.'+ms;
        while (t.length < 5)
          t += '0';
      } // if (secs < 10)
      else if (secs < 1000) {
        if (secs < 100)
          t = ' ';
        msstring = ''+ms;
        t += secs+'.'+msstring[0];
      } // else if (secs < 1000)
      else {
        var secsString = ''+secs;
        var i = secsString.length;
        while (i<5) {
          t+= ' ';
          i++;
        } // while (i<5)
        t += secsString;
      } // else (secs < 1000)
    } // else (ms >= msDay)
  } // else (traceTime == null)
  traceTime = time;
  return t;
} // timeStamp()

/* Will output the text, if the level is enabled. If traceInit() hasn't 
   been called then all traces are disabled, and nothing will be traced.
   This is the easiest way of disabling tracing, removing the call to
   traceInit().
/* =================================================================== */
function trace ( level, text ) {
  var t;

  if ( traceEnable[ level ] ) {
    t = timeStamp()+' : ';
    t += levelText[level];
    while (t.length < 15)
      t+= ' ';
    doTrace( t + ' : ' + text );
  }
}

/* Enable or disable traces */
function traceSet( level, value ) {
  traceEnable[ level ] = value; 
}

/* test if console is present. Disable tracing if trap caught */
function probeTrace( s ) {
  try {
    console.log( s );
  } catch( err ) {
    consoleFound = false;
  }
}

/* The normal trace driver after console has been probed */
function doTrace( s ) {
  if ( consoleFound )
    console.log( s );
}


