// testHandleRec -- Illustration of using the handle recovery features of
//		    the ErrorLogger mechanism.
//
// This example program is in two logical pieces:
//
//	First we show the user code -- many physicist users could contribute
//	code of this nature, using errlog in the manner shown.
//
//	Then we show the framework code that would support this.  One
//	programmer sets up this framework to coordinate all code.  The
//	framework controls things like which output destinations exist and
//	what sort of messages to pass to each destination.
//
// 	THIS FRAMEWORK IS A VERY MINIMAL EXAMPLE for illustration.
//
// 	A more realistic framework that one could start from for
//	customizing a framework for production is in frameworkExample.cc.
//
//	The test program is very similar to that of BasicUsage.cc, and in fact
//	shares the header file for that test.

// -----------------
// Physicsists' Code
// -----------------

#include "basicUsage.h"
	// Would normally include some framework.h; but in this example we
	// are keeping everything together in one .cc and one .h file.
	//
	// Would also include DoPhysics.h, but that is also in basicUsage.h.

#include "ErrorLogger/ErrorLog.h"
	// This is the only ErrorLogger-related include the user normally needs.
#include "ErrorLogger/ELdestControl.h"
	// But for this test, we have the phsycicist's code controlling a dest!

void DoPhysics::operator()( Event & event )  {

  // THIS METHOD IS WHERE ALL THE PHYSICS CALCULATION WOULD GO.

  // Here, we always log an ELsuccess and an ELerror2.
  // At the start, both should be emitted.
  // But after event 5, we raise the threshold to ELerror, so that
  // only the ELerror2 will come out.
  // Also, after event 10, we will suppress the time only in the log,
  // and after event 15, we will re-lower the threshold only in the out.
  // Finally, at event 17, we intentionally sccrew up the names used to
  // get handles, to verify that the resulting handles are null.

  errlog( ELsuccess, "An Event" ) << "data = " << event.data << endmsg;
  errlog( ELerror2,  "An Error" ) << "data = " << event.data << endmsg;

  if ( event.data == 5 ) {
    ELdestControl log;
    bool handleFound;
    handleFound = errlog.getELdestControl ("log", log);
    if (!handleFound) { 
      std::cout << "TERRIBLE PROBLEM -- Handle to log not found\n";
      exit(-1);
    }
    ELdestControl out;
    handleFound = errlog.getELdestControl ("out", out);
    if (!handleFound) { 
      std::cout << "TERRIBLE PROBLEM -- Handle to out not found\n";
      exit(-1);
    }
    log.setThreshold(ELerror2);
    out.setThreshold(ELerror2);
  }

  if ( event.data == 10 ) {
    ELdestControl log;
    bool handleFound;
    handleFound = errlog.getELdestControl ("log", log);
    if (!handleFound) { 
      std::cout << "TERRIBLE PROBLEM -- Handle to log not found\n";
      exit(-1);
    }
    log.suppressTime();
  }

  if ( event.data == 15 ) {
    ELdestControl out;
    bool handleFound;
    handleFound = errlog.getELdestControl ("out", out);
    if (!handleFound) { 
      std::cout << "TERRIBLE PROBLEM -- Handle to out not found\n";
      exit(-1);
    }
    out.setThreshold(ELsuccess);
  }

  if ( event.data == 15 ) {
    ELdestControl out;
    bool handleFound;
    handleFound = errlog.getELdestControl ("out", out);
    if (!handleFound) { 
      std::cout << "TERRIBLE PROBLEM -- Handle to out not found\n";
      exit(-1);
    }
    out.setThreshold(ELsuccess);
  }

  if ( event.data == 17 ) {
    ELdestControl log;
    bool handleFound;
    handleFound = errlog.getELdestControl ("not_log", log);
    if (handleFound) { 
      std::cout << "TERRIBLE PROBLEM -- Handle to not_log found\n";
      exit(-1);
    }
    ELdestControl out;
    handleFound = errlog.getELdestControl ("not_out", out);
    if (handleFound) { 
      std::cout << "TERRIBLE PROBLEM -- Handle to not_out found\n";
      exit(-1);
    }
    log.setThreshold(ELfatal);	// These should have no effect!
    out.setThreshold(ELfatal);	// These should have no effect!
  }

} // DoPhysics::operator()(event)

// ---------------
// Framework Code
// ---------------

#include "basicUsage.h"
	// The framework would normally include some framework.h, plus Event.h,
	// Module.h, and the headers for any physicist classes like DoPhysics.
	// In our illustration these are all in basicUsage.h.

// These are the ErrorLogger classes used by the typical framework:

#include "ErrorLogger/ELadministrator.h"
#include "ErrorLogger/ELdestControl.h"
#include "ErrorLogger/ELoutput.h"
#include "ErrorLogger/ELstatistics.h"

#include "ZMutility/iostream"
USING( std::cout )

Module::Module( const std::string & name )  {
  errlog.setModule( name );	
}

int main()  {

  ELadministrator * logger = ELadministrator::instance();
    // instantiate a logger object

  ELoutput      logfileD( "handleDest.errlog" );      // make an ELdestination
  ELdestControl logfile ( logger->attach(logfileD, "log") ); 
		// tell logger about it and name it log for id purposes
  logfile.setThreshold  ( ELsuccess );    	      // ignore messages below
						      // ELsucess

  ELoutput      outputD( cout );                      // another ELdestination
  ELdestControl output ( logger->attach(outputD, "out") );   
						      // tell logger about it
  output.setThreshold  ( ELsuccess );     	      // ignore messages below
						      // ELsuccess

  ELstatistics  statsD( cout );			      // a statistics dest
  ELdestControl stats ( logger->attach(statsD) );     // tell logger about it

  // The following is a list of the modules in this program:
  DoPhysics  doPhysics(  "PHYSICS CODE" );
	// There is only one module in this illustration.

  int n;
  for ( n = 1;  n < 20;  ++n )  {
    Event event( n );
    doPhysics( event );
  }

  return 0;

}  // main()
