// client.cpp : Defines the class behaviors for the application.
//

#include "gui/stdafx.h"
#include "client.h"
#include <string.h>
#include "tao/ORB_Core.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CLrsClient

BEGIN_MESSAGE_MAP(CLrsClient, CWinApp)
	//{{AFX_MSG_MAP(CLrsClient)	
		// NOTE - the ClassWizard will add and remove mapping macros here.
		//    DO NOT EDIT what you see in these blocks of generated code!
	//}}AFX_MSG_MAP
	// Standard file based document commands
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CLrsClient construction

CLrsClient::CLrsClient()
:_lrsEventConsumer_i(this),
_argc (0)
{
	// Initialize singleton LrsConnectionStatus and housekeeping
	// alarm setpoints
   LrsConnectionStatus::instance()->init(this);
   
	for(int i=0; i<NUM_HOUSINGS; i++) {
		_setpoints[i].overrh = DEFAULT_OVER_RH;
		_setpoints[i].warnrh = DEFAULT_WARN_RH;
		_setpoints[i].overtemp = DEFAULT_OVER_TEMP;
		_setpoints[i].warntemp = DEFAULT_WARN_TEMP;
	}

	// Place all significant initialization in InitInstance
}

CLrsClient::~CLrsClient()
{	
	char str[32];

	for(int id=0; id <NUM_HOUSINGS; id++) {
	if(_setpointCfg[id].temp()) { //if valid cfg pointer
		
		sprintf(str, "%12.2lf", _setpoints[id].warntemp);
		_setpointCfg[id].temp()->replace(0, str);

		sprintf(str, "%12.2lf", _setpoints[id].overtemp);
		_setpointCfg[id].temp()->replace(1, str);

		_lrsCfg.replaceConfigItem(_setpointCfg[id].temp);
	   }

	if(_setpointCfg[id].rh()) { //if valid cfg pointer
		
		sprintf(str, "%12.2lf", _setpoints[id].warnrh);
		_setpointCfg[id].rh()->replace(0, str);

		sprintf(str, "%12.2lf", _setpoints[id].overrh);
		_setpointCfg[id].rh()->replace(1, str);

		_lrsCfg.replaceConfigItem(_setpointCfg[id].rh);
	   }

	}
	// Update the lrs configuration file
	_lrsCfg.saveConfigItems();	

	
	// Clean up argv array
	while(_argc-- > 0)
		free((void *) _argv[_argc]);
}

/////////////////////////////////////////////////////////////////////////////
// The one and only CLrsClient object

CLrsClient theApp;

/////////////////////////////////////////////////////////////////////////////
// CLrsClient initialization

BOOL CLrsClient::InitInstance()
{
   char *token;   


   AfxEnableControlContainer();

    // Standard initialization
	// If you are not using these features and wish to reduce the size
	//  of your final executable, you should remove from the following
	//  the specific initialization routines you do not need.

#ifdef _AFXDLL
	Enable3dControls();			// Call this when using MFC in a shared DLL
#else
	Enable3dControlsStatic();	// Call this when linking to MFC statically
#endif

   // Arg line should look something like
   // client.exe LRS -ORBInitRef NameService=corbaloc:iiop:surfperch:20001/NameService -ORBLogFile .\client.log
   token = strtok(&m_lpCmdLine[0], " \n\r" );

   // Parse out tokens into argv[] array
   while(token != 0){				
	   _argv[_argc] = strdup(token);
	   token = strtok(NULL, " \n\r" ); //search for next token delimiters
	   _argc++;
   }

   // Initialize the alarm setpoints from the lrs.cfg file
   _lrsCfg.initialize();

   initSetpoints("LRS-E1", ELECTRONICS_HOUSING);
   initSetpoints("LRS-S1", SPECTROGRAPH_HOUSING);
   
   // Initialize main dialog window
   m_pMainWnd = &this->_dialog;

   // Initialize client
   if(initCORBAClient() == TRUE) {	   
   	   // Create the client window
	   _dialog.Create();
	    //Activates the window and displays it as a maximized window
	   _dialog.ShowWindow(SW_SHOWNORMAL);
	   return TRUE;
   }

   return FALSE;	
}


void CLrsClient::close()
{
	ACE_TRY 
	{
		// A wrapper class containing all ORB IDL proxy interfaces
		// close all interfaces
		_interfaceClient.close();

		// Close instance of the consumer. Close initiaited from consumer(TRUE)
		// This will kill task that monitors for events from the server. 
		this->_consumer.close(TRUE);

	}
	ACE_CATCHANY
	{
		ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,"Unexpected exception\n");
		
	}
	ACE_ENDTRY;

	LrsConnectionStatus::instance()->set(FALSE);	
}


void CLrsClient::shutdown()
{
	this->_consumer.close(FALSE);
	_interfaceClient.close();
	LrsConnectionStatus::instance()->set(FALSE);	
}


void CLrsClient::initSetpoints(const char *cfgname, HousingID id)
{	
	   ConfigItemWrapper cfgitem;
	   char tempname[128];	   

	   sprintf(tempname, "%s-%s", cfgname, "TEMP_ALARM_SETPOINTS");	   
	   if(_lrsCfg.searchForConfigItem(tempname, cfgitem) && cfgitem()->nitems() == 2) {
		   _setpoints[id].warntemp = atoi(cfgitem()->parm(0));
		   _setpoints[id].overtemp = atoi(cfgitem()->parm(1));

		   _setpointCfg[id].temp = cfgitem;
	   }

	   memset(tempname, NULL, sizeof(tempname));
	   sprintf(tempname, "%s-%s", cfgname, "RH_ALARM_SETPOINTS");
	   if(_lrsCfg.searchForConfigItem(tempname, cfgitem) && cfgitem()->nitems() == 2) {
		   _setpoints[id].warnrh = atoi(cfgitem()->parm(0));
		   _setpoints[id].overrh = atoi(cfgitem()->parm(1));

		   _setpointCfg[id].rh = cfgitem;
	   }
}


BOOL CLrsClient::initCORBAClient()
{
	// Initialize the Consumer object reference.
   if (_consumer.initialize (_argc, _argv, &this->_lrsEventConsumer_i) == -1) {	   
	   ACE_ERROR((LM_ERROR,	"%p\n", "Consumer init failed\n"));
	   AfxMessageBox("Event consumer init failed. See ""client.log"" for details", MB_OK);	   
	   return FALSE;
   }  

   // Initialize the lrs object interface
   if(_interfaceClient.initialize(TAO_ORB_Core_instance()->orb()) == -1){
	   ACE_ERROR((LM_ERROR,	"%p\n", "LRS target interface initialize failed\n"));
	   AfxMessageBox("Event consumer run failed. See ""client.log"" for details", MB_OK);
	   return FALSE;
   }


   // Run the consumer thread if init succeeds
   if(_consumer.run() == -1) {
	   ACE_ERROR((LM_ERROR,	"%p\n", "Consumer run failed\n"));
	   AfxMessageBox("Event consumer run failed. See ""client.log"" for details", MB_OK);
	   return FALSE;
   }

   // Update the connection status
   LrsConnectionStatus::instance()->set(TRUE);
   return TRUE;
}

BOOL CLrsClient::reconnectCORBAClient()
{
   if(!LrsConnectionStatus::instance()->isConnected()) {

   // Initialize the lrs object interface
   if(_interfaceClient.initialize(TAO_ORB_Core_instance()->orb()) == -1){
	   ACE_ERROR((LM_ERROR,	"%p\n", "LRS target interface initialize failed\n"));
	   AfxMessageBox("LRS CLIENT reconnect failed. See ""client.log"" for details", MB_OK);
	   return FALSE;
   }

   LrsConnectionStatus::instance()->set(TRUE);
   return TRUE;
   }

   return FALSE;
}