//////////////////////////////////////////////////////////////////////
// LrsApp.cpp: implementation of the LrsApp class.
//
//////////////////////////////////////////////////////////////////////
#include "lrsapp.h"
#include "appinfo.h"
#include "debug.h"
#include "errorlog.h"
#include "tasksynchronizer.h"
#include "exceptions.h"
#include "osutils.h"

/////////////////////////////////////////////////////////////////////
// LrsApp Construction/Destruction
//////////////////////////////////////////////////////////////////////
LrsApp::LrsApp()	
: MicroApp(ApplicationInfo::title(),"LaserRamanSystem"),
_pLrsCfg(0),
_pLrsEventHandler(0),
_pLrsSampler(0),
_pSupplier(0),
_pSpectrographSensor(0),
_pElectronicsSensor(0),
_shutdown(0),
_appstate(STARTUP)
{	
	_TRY_ 
	{
	_pAlarmManager = AlarmManager::instance();	
	_pAlarmManager->activate("AlarmMgr",
						 THREAD_PRIORITY_NORMAL,										 
						 0, // flags
						 4096 //stacksize
						 );		

	if((_pLrsCfg = new LrsCfg()) == NULL)
		::exit(0);

	if((_pSupplier = new Supplier(&this->_thrManager, this)) == NULL)
		::exit(0);

	if((_pSpectrographSensor = new HousekeepingSensors("Spectrograph Housing")) == NULL)
		::exit(0);

	if((_pElectronicsSensor = new HousekeepingSensors("Electronics Housing")) == NULL)
		::exit(0);
	}
	_CATCH_(Exception, e)
	{
		printf("%s\n",e.msg());
		ErrorLog::logError(e.msg());
		_THROW_(Exception(0, e.msg())); //re-throw the exception
	}

}
LrsApp::~LrsApp()
{
	if(_pSupplier != NULL)
		delete _pSupplier;

	if(_pLrsCfg != NULL)
		delete _pLrsCfg;

	if(this->_pLrsEventHandler != NULL)
		delete _pLrsEventHandler;

	if(this->_pLrsSampler != NULL)
		delete _pLrsSampler;

	if(this->_pElectronicsSensor != NULL)
		delete _pElectronicsSensor;

	if(this->_pSpectrographSensor != NULL)
		delete _pSpectrographSensor;

	//This must always be deleted last
	if(_pAlarmManager != NULL)
		delete _pAlarmManager;
}

MicroEventHandler *LrsApp::createEventHandler()
{
	_TRY_
	{
	_pLrsEventHandler = new LrsEventHandler(ApplicationInfo::title(), this);			
	return((MicroEventHandler *) _pLrsEventHandler);
	} //end try	
	_CATCH_(Exception, e)
	{
		DPRINTF("LrsApp::createEventHandler %s\n", e.msg());
	}
	return 0;
}

MicroPeriodicHandler *LrsApp::createPeriodicHandler()
{
	_TRY_
	{
	_pLrsSampler = new LrsSampler(ApplicationInfo::title(), this);			
	return((MicroPeriodicHandler *) _pLrsSampler);
	}//end try
	_CATCH_(Exception, e)
	{
		DPRINTF("LrsApp::createPeriodicHandler %s\n", e.msg());
	}
	return 0;

}

Void LrsApp::setTaskParams()
{
  // initialize task params
  // Initialize task params to something reasonable
  _eventHandlerParams.priority = THREAD_PRIORITY_ABOVE_NORMAL;
  _eventHandlerParams.floatingPoint = TRUE;
  _eventHandlerParams.stackSize = 5000;  
  
  _periodicHandlerParams.priority = THREAD_PRIORITY_TIME_CRITICAL;
  _periodicHandlerParams.floatingPoint = TRUE;
  _periodicHandlerParams.stackSize = 5000;

}
int LrsApp::runApp()
{
	char msg[128];	
	static Nat16 ntrys;
	static Nat16 cnt;
	Time gmtFormatTime;	
	Nat16 freq = 0;

	switch(_appstate)
	{
	case(STARTUP):	
		// Reset Mission Start Time to current time.
		_mst = Clock::getgmTime();
		// Start supplier		
		_appstate++;
		break;
	case(RUN):		
		//Run supplier
		_pSupplier->activate();
		_appstate++;
		break;
	case(WAITFORSHUTDOWN):
		Utility::delay(1000);
		if(this->isShutdown())
			_appstate++;
		break;
	case(CLEAN_UP):
		// Update the lrs configuration file
		_pLrsCfg->saveConfigItems();
		_appstate++;
		break;
	case(SHUTDOWN):
		ErrorLog::logMsg("Application shutdown started...");				
		Utility::delay(500);
		MicroApp::exit();  // Shutdown the framework		
		if(MicroApp::error()){
			MicroApp::errorMsg(msg);
			ErrorLog::logError(msg);
		}

		Utility::delay(4000);

		// Shutdown supplier last so client gui gets all the message and
		// data generated during shutdown
		_pSupplier->close();	 
		
		// Close the input handler last
		_ih.close ();  

		// Wait for all threads managed by thr_Manager to exit.  
		_thrManager.wait ();
	default:
		break;
	}
	return 0;

}
int LrsApp::initialize(int argc, char *argv[])
{	
	//Initialize message/alarm log file
	ErrorLog::logMsg("Initializing alarm/msg log file");
	_pAlarmManager->initialize(this->_pSupplier);

	//Init the appframework
	MicroApp::initialize(argc, argv);

	//Read and parse cfg file
	ErrorLog::logMsg("Reading lrs.cfg file");	
	_pLrsCfg->initialize();	
	
	ErrorLog::logMsg("Initializing houskeeping sensors");	
	//Initialize the houskeeping sensors
	if(_pSpectrographSensor->init("LRS-S1", _pLrsCfg) == -1) {
		ErrorLog::logError("Error initializing electronics housing sensors");
		return -1;
	}

	if(_pElectronicsSensor->init("LRS-E1", _pLrsCfg) == -1) {
		ErrorLog::logError("Error initializing spectrograph housing sensors");
		return -1;
	}

	ErrorLog::logMsg("Initializing event supplier");	
	// Initialize the event supplier
	if (_pSupplier->init (argc, argv) == -1) {
		ErrorLog::logError("Event supplier init failed");
		return -1;
	}
	
	ErrorLog::logMsg("Initializing keyboard input handler");	
	//Initialize the keyboard input handler
	if(_ih.initialize(_pSupplier) == -1) {
		ErrorLog::logError("Error initializing keyboard input handler");
		return -1;
	}

	return 0;
}

int LrsApp::exit()
{
	shutdown();	
	return 0;
}


void LrsApp::shutdown()
{
	// Set shutdown flag
	ErrorLog::logMsg("Application shutdown requested");				
	_shutdown = 1;

	// Shutdown any active tasks here	
}
MBool LrsApp::isShutdown()
{	
	return _shutdown;	
}

	// Returns current LrsApp state
LrsApp::State LrsApp::state()
{
	return (State)_appstate;
}
	
void LrsApp::resetWatchdog(CallbackObject *)
{
	//TODO: add watchdog reset function
}

Int32 LrsApp::elapsedTime()
{
	return (Clock::getgmTime() - _mst);
}

