// Ex07aDialog.cpp : implementation file
//

#include "gui\stdafx.h"
#include "gui\clientdialog.h"
#include "gui\alarmdialog.h"
#include "gui\wmmessage.h"
#include "client.h"


#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

extern CLrsClient theApp;

enum waterAlarmIndex {ALARM_OFF, ALARM_ON};

const char *waterAlarmMessage[] = {
	"OK          ",
	"ALARM ON    "
};

/////////////////////////////////////////////////////////////////////////////
// CLrsClientDialog dialog

CLrsClientDialog::CLrsClientDialog(CWnd* pParent /*=NULL*/)
	: CDialog(CLrsClientDialog::IDD, pParent),
	_theApp(&theApp),
	m_pStatusDialog(0),
	m_pLinkProgress(0),
	m_pLinkIndicator(0),
	m_pTimeIndicator(0)
{
	TRACE("CLrsClientDialog::CLrsClientDialog\n");
	for(int i=0; i<NUM_HOUSINGS; i++) {
		m_pAlarmDialog[i] = 0;
		m_waterAlarmColor[i] = BAD_READING_COLOR;
	}


	//{{AFX_DATA_INIT(CLrsClientDialog)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT	
}
CLrsClientDialog::~CLrsClientDialog()
{
	if(m_pLinkProgress != 0)
		delete m_pLinkProgress;

	if(m_pStatusDialog != 0)
		delete m_pStatusDialog;

	for(int i=0; i<NUM_HOUSINGS; i++)
		if(m_pAlarmDialog[i] != 0)
			delete m_pAlarmDialog[i];

	if(m_pLinkIndicator != 0)
		delete m_pLinkIndicator;

	if(m_pTimeIndicator != 0)
		delete m_pTimeIndicator;

}

void CLrsClientDialog::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CLrsClientDialog)
		// NOTE: the ClassWizard will add DDX and DDV calls here
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CLrsClientDialog, CDialog)
	ON_MESSAGE(WM_EVENT, OnEvent)
	//{{AFX_MSG_MAP(CLrsClientDialog)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_WM_DESTROY()
	ON_BN_CLICKED(IDC_BUTTON_CHANGE_ELECT_SP, OnButtonChangeElecSetpoints)
	ON_BN_CLICKED(IDC_BUTTON_CHANGE_SPECT_SP, OnButtonChangeSpectSetpoints)
	ON_WM_CTLCOLOR()
	ON_BN_CLICKED(IDSHOWSTATUS, OnShowStatus)
	ON_BN_CLICKED(IDRECONNECT, OnReconnectToTarget)
	ON_WM_TIMER()
	ON_WM_SHOWWINDOW()
	ON_WM_LBUTTONDOWN()
	ON_WM_CANCELMODE()
	ON_WM_RBUTTONDOWN()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CLrsClientDialog message handlers

BOOL CLrsClientDialog::OnInitDialog()
{
	CDialog::OnInitDialog();

/*/////////////////////////////////////////////////
	custom initialization
//////////////////////////////////////////////////*/	

//////////////////////////////////////////////////*/	
//Init blink link indicator and elapsed time indicators 
//////////////////////////////////////////////////*/	
	m_pLinkIndicator = new CLinkIndicator(IDC_MICRO_LINK_STATE2, 
							LrsConnectionStatus::instance(), 
							this, IDB_LED_OFF, IDB_LED_ON, IDB_LED_CLR);

	m_pTimeIndicator = new CTimeIndicator(IDC_ELAPSED_CONNECTION_TIME2,IDC_ELAPSED_TARGETON_TIME2, 
							LrsConnectionStatus::instance(),
							this);
	
//////////////////////////////////////////////////*/	
//Init temp and humidity bar displays
//////////////////////////////////////////////////*/	
	
	CString s;
	CWnd *pMinTxt;
	CWnd *pMaxTxt;
	WINDOWPLACEMENT wndMinPl, wndMaxPl;
	int height;
	int xmin;
	int ymin;
	int width;
	
	for(int id=0; id<NUM_HOUSINGS; id++) {

	pMinTxt = GetDlgItem(IDC_MINTEMP + id);
	pMaxTxt = GetDlgItem(IDC_MAXTEMP + id);
	
	pMinTxt->GetWindowPlacement(&wndMinPl);
	pMaxTxt->GetWindowPlacement(&wndMaxPl);

	height = 30;
	xmin = wndMinPl.rcNormalPosition.left;
	ymin = wndMinPl.rcNormalPosition.top - height;
	width = wndMaxPl.rcNormalPosition.right - xmin;	

	m_TemperatureBar[id].Create(this,		// parent object
		xmin,					// upper left corner of bar
		ymin,
		width,					// width of bar
		height,					// height of bar
		TRUE,					// use 3D border around bar
		TRUE,					// use counter text if solid bar type
		GOOD_COLOR,				// foreground (bar)color
		RGB(192,192,192));		// background color

	m_TemperatureBar[id].ClearMeter();
	m_TemperatureBar[id].SetFormat("°C");

	s.Format("%d °C", MIN_TEMP_DISPLAY);	
	SetDlgItemText(IDC_MINTEMP + id ,s);

	s.Format("%d °C", MAX_TEMP_DISPLAY);	
	SetDlgItemText(IDC_MAXTEMP + id,s);

	//////////////////////////////////////////////////*/	
	
	pMinTxt = GetDlgItem(IDC_MINRH + id);
	pMaxTxt = GetDlgItem(IDC_MAXRH + id);

	pMinTxt->GetWindowPlacement(&wndMinPl);
	pMaxTxt->GetWindowPlacement(&wndMaxPl);

	height = 30;
	xmin = wndMinPl.rcNormalPosition.left;
	ymin = wndMinPl.rcNormalPosition.top - height;
	width = wndMaxPl.rcNormalPosition.right - xmin;	
	
	m_RHBar[id].Create(this,	// parent object
		xmin,					// upper left corner of bar
		ymin,
		width,					// width of bar
		height,					// height of bar
		TRUE,					// use 3D border around bar
		TRUE,					// use counter text if solid bar type
		GOOD_COLOR,				// foreground (bar)color
		RGB(192,192,192));		// background color

	m_RHBar[id].ClearMeter();
	m_RHBar[id].SetFormat("%");

	s.Format("%d %%", MIN_RH_DISPLAY);	
	SetDlgItemText(IDC_MINRH + id,s);

	s.Format("%d %%", MAX_RH_DISPLAY);	
	SetDlgItemText(IDC_MAXRH + id,s);

	SetDlgItemText(IDC_WATER_SENSOR + id, "INVALID DATA");			
	m_TemperatureBar[id].ChangeForeColor(BAD_READING_COLOR);
	m_TemperatureBar[id].ClearMeter();	
	m_TemperatureBar[id].Meter((long)BADREADING, (long)MIN_TEMP_DISPLAY, (long)MAX_TEMP_DISPLAY);		
	m_RHBar[id].ChangeForeColor(BAD_READING_COLOR);
	m_RHBar[id].ClearMeter();	
	m_RHBar[id].Meter((long)BADREADING, (long)MIN_TEMP_DISPLAY, (long)MAX_TEMP_DISPLAY);		
	

	}//end for id < NUM_HOUSINGS

//////////////////////////////////////////////////*/	
//Create client display, status dialog, and alarm set in separate windows
//////////////////////////////////////////////////*/	

	m_pStatusDialog = new CLrsStatusDialog(this);
	m_pStatusDialog->Create(this);
	// Do not show the status dialog unless requested
	
	m_pAlarmDialog[ELECTRONICS_HOUSING] = new CAlarmSetpointDialog(this);
	m_pAlarmDialog[ELECTRONICS_HOUSING]->Create(this, "LRS Electronics Housing Setpoints", &_theApp->_setpoints[ELECTRONICS_HOUSING]);

	m_pAlarmDialog[SPECTROGRAPH_HOUSING] = new CAlarmSetpointDialog(this);
	m_pAlarmDialog[SPECTROGRAPH_HOUSING]->Create(this, "LRS Spectrometer Housing Setpoints", &_theApp->_setpoints[SPECTROGRAPH_HOUSING]);
	// Do not show the alarm dialog until needed
//////////////////////////////////////////////////*/	
//Init progress bar for CORBA connect/disconnect status
//////////////////////////////////////////////////*/	
	m_pLinkProgress = new CProgressCtrlDialog(this);
	m_pLinkProgress->Create(this, "LRS Connect Progress", CProgressCtrlDialog::CONNECT);
	m_pLinkProgress->ShowWindow(SW_SHOWNORMAL);	//Activates and displays this window

	//UpdateData(FALSE);

//////////////////////////////////////////////////
// Add timer to update link state
	m_nTimer = SetTimer(1,1000, NULL); //~1 second
	ASSERT(m_nTimer != 0);
/*/////////////////////////////////////////////////
	end custom initialization
//////////////////////////////////////////////////*/

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon
	
	
	// TODO: Add extra initialization here

	
	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CLrsClientDialog::OnSysCommand(UINT nID, LPARAM lParam)
{
	CDialog::OnSysCommand(nID, lParam);
}
/*/////////////////////////////////////////////////
// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.
//////////////////////////////////////////////////*/
void CLrsClientDialog::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CLrsClientDialog::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

BOOL CLrsClientDialog::Create()
{	
	return CDialog::Create(CLrsClientDialog::IDD);
}


/////////////////////////////////////////////////////////////////////////////
// CLrsClientDialog message handlers

void CLrsClientDialog::OnCancel()  // not really a message handler
{
	if (_theApp != NULL) {
		// modeless case -- do not call base class OnCancel
		UpdateData(TRUE);
		_theApp->close();
	}

	//////////////////////////////////////////////////*/	
	//Init progress bar for CORBA connect/disconnect status
	//////////////////////////////////////////////////*/	
	m_pLinkProgress->Create(this, "LRS Disconnect Progress", CProgressCtrlDialog::DISCONNECT);
	m_pLinkProgress->ShowWindow(SW_SHOWNORMAL);	//Activates and displays this window	
}

void CLrsClientDialog::UpdateHKDisplay(LRS::HousekeepingData *data)
{
	//get temperature
	//temp = DEGREESC_TO_F(pTempCtrl->GetTemp(szDataResponse));
	// Convert temp to Farenheit

	double temp = (double) data->temp;
	long rh = (long) data->rh;
	HousingID id = data->id;
	unsigned int wateralarm = (unsigned int) data->wateralarm;

	/////////////////////////////////////////////////////////////
	// Update water alarm display
	if(wateralarm != BADREADING) {
		if(wateralarm == TRUE)		
			m_waterAlarmColor[id] = ALARM_COLOR;
		else
			m_waterAlarmColor[id] = SYSTEM_GREY;

		SetDlgItemText(IDC_WATER_SENSOR + id, waterAlarmMessage[wateralarm]);			
	}
	else {
		m_waterAlarmColor[id] = BAD_READING_COLOR;
		SetDlgItemText(IDC_WATER_SENSOR + id, "INVALID DATA");			
	} 

	if(temp != BADREADING) {
		
		// Check alarm status
		if(temp > _theApp->_setpoints[id].overtemp)
			m_TemperatureBar[id].ChangeForeColor(ALARM_COLOR);
		else if(temp > _theApp->_setpoints[id].warntemp)
			m_TemperatureBar[id].ChangeForeColor(WARNING_COLOR);
		else 
			m_TemperatureBar[id].ChangeForeColor(GOOD_COLOR);
	} 
	else 
		m_TemperatureBar[id].ChangeForeColor(BAD_READING_COLOR);	
		
	
	m_TemperatureBar[id].Meter(temp, (long)MIN_TEMP_DISPLAY, (long)MAX_TEMP_DISPLAY);		

	
	if(rh != BADREADING) {		
		// Check alarm status
		if(rh > _theApp->_setpoints[id].overrh)
			m_RHBar[id].ChangeForeColor(ALARM_COLOR);
		else if(rh > _theApp->_setpoints[id].warnrh)
			m_RHBar[id].ChangeForeColor(WARNING_COLOR);
		else 
			m_RHBar[id].ChangeForeColor(GOOD_COLOR);
	} 
	else 
		m_RHBar[id].ChangeForeColor(BAD_READING_COLOR);	
	
	m_RHBar[id].Meter(rh, (long)MIN_RH_DISPLAY, (long)MAX_RH_DISPLAY);		
}

LRESULT CLrsClientDialog::OnEvent(WPARAM wParam, LPARAM lParam)
{
	// message received in response to Event_Comm::push

	TRACE("CLrsClientDialog::OnEvent %x, %lx\n", wParam, lParam);

	LRS::Event *evt;
	LRS::Message tempmsg;
	CORBA::TypeCode_ptr tc_ptr = (CORBA::TypeCode_ptr) wParam;
	time_t ltime = 0;	

	if(tc_ptr && lParam && wParam) //if valid typecode and data pointer to data use
	{    
		//Process messages
		/////////////////////////////////////////////
		//Event message. These occur as a result of system state transitions e.g. 
		//alarms on/off, etc.
		if(tc_ptr->equal(LRS::_tc_Event)) {
			evt = (LRS::Event *)lParam;
			TRACE("Event ID: %d name: %s arrival_time: %d\n", 
			evt->id,
			evt->name.in(),
			evt->arrival_time);	
		}
		////////////////////////////////////////////
		//Houskeeping data event
		else if(tc_ptr->equal(LRS::_tc_HousekeepingData)) {
			UpdateHKDisplay((LRS::HousekeepingData *)lParam);
			if(((LRS::HousekeepingData *)lParam)->id == ELECTRONICS_HOUSING)
				m_pAlarmDialog[ELECTRONICS_HOUSING]->SendMessage(WM_HOUSEKEEPINGDATA, 0, lParam);	
			else
				m_pAlarmDialog[SPECTROGRAPH_HOUSING]->SendMessage(WM_HOUSEKEEPINGDATA, 0, lParam);
		}
		////////////////////////////////////////////
		//Message event. Could be message, alarm or warning message
		else if(tc_ptr->equal(LRS::_tc_Message)) {
			if(this->m_pStatusDialog != 0) //if status dialog valid
				m_pStatusDialog->SendMessage(WM_MESSAGE, 0, lParam);//send message ptr reference in lParam
		}
		////////////////////////////////////////////
		//String message. Stuff into a LRS::Message and send
		else if(tc_ptr->equal(CORBA::_tc_string)){
			if((char *)lParam != 0) {
				tempmsg.text = CORBA::string_alloc(strlen((char *)lParam));
				strcpy(tempmsg.text.inout(), (char *)lParam);
				tempmsg.priority = MESSAGE;								
				time( &ltime ); // Return UTC time
				tempmsg.arrival_time = ltime;
				m_pStatusDialog->SendMessage(WM_MESSAGE, 0, (WPARAM) &tempmsg);//send message ptr reference in lParam
				CORBA::string_free(tempmsg.text.out());				
			}
		}
		else {}		

	}//end if
	return 0L;
}

////////////////////////////////////////////////////////////////////////////
// CProgressCtrlDialog dialog


CProgressCtrlDialog::CProgressCtrlDialog(CWnd* pParent /*=NULL*/)
	: CDialog(CProgressCtrlDialog::IDD, pParent),
	_theApp(&theApp)
{
	//{{AFX_DATA_INIT(CProgressCtrlDialog)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
}


void CProgressCtrlDialog::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CProgressCtrlDialog)
		// NOTE: the ClassWizard will add DDX and DDV calls here
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CProgressCtrlDialog, CDialog)
	//{{AFX_MSG_MAP(CProgressCtrlDialog)
	ON_WM_TIMER()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CProgressCtrlDialog message handlers

BOOL CProgressCtrlDialog::Create(CWnd* pParent, const char *dialogTitle, displayMode mode) 
{
	// TODO: Add your specialized code here and/or call the base class
	_mode = mode;
	_parent = pParent;
	// Create window as child of parent
	CDialog::Create(CProgressCtrlDialog::IDD, pParent);
	SetWindowText(dialogTitle);	
	_title = CString(dialogTitle);
	return TRUE;
}

BOOL CProgressCtrlDialog::OnInitDialog() 
{
	CDialog::OnInitDialog();

	CProgressCtrl *ctrl = (CProgressCtrl *)GetDlgItem(IDC_PROGRESS_BAR);
	
	// TODO: Add extra initialization here	
	ctrl->SetRange(0,100);  //This is a 0 - 100% indicator
	ctrl->SetStep(1);
	ctrl->SetPos(0);

	m_timerID = SetTimer(1,1000, NULL); //~1 seconds
	ASSERT(m_timerID != 0);
	
	return TRUE;  // return TRUE unless you set the focus to a control
	              // EXCEPTION: OCX Property Pages should return FALSE
}

void CProgressCtrlDialog::OnTimer(UINT nIDEvent) 
{
	CProgressCtrl *ctrl = (CProgressCtrl *)GetDlgItem(IDC_PROGRESS_BAR);
	CString s = _title;	
	
	// TODO: Add your message handler code here and/or call default
	if(_mode == CONNECT) { 
	switch(_theApp->_consumer.initState())
	{
	case(Consumer::NOT_STARTED):		
		s += " - NOT STARTED";
		SetWindowText(s);
		ctrl->SetPos(0);
		break;
	case(Consumer::IN_PROGRESS):		
		s += " - IN PROGRESS";
		SetWindowText(s);
		ctrl->StepIt();
		break;
	case(Consumer::COMPLETE):
		s += " - COMPLETE";
		SetWindowText(s);
		ctrl->SetPos(100);
		CDialog::DestroyWindow();
		break;
	case(Consumer::FAILED):
		s += " - FAILED";
		SetWindowText(s);
		ctrl->SetPos(0);
		ctrl->KillTimer(m_timerID);
		CDialog::DestroyWindow();
		break;
	default:
		ctrl->KillTimer(m_timerID);
		CDialog::DestroyWindow();
		break;
	}	
	}
	else if(_mode == DISCONNECT)
	{
		if(_theApp->_consumer.isShutdown() || !LrsConnectionStatus::instance()->isConnected()) 
		{
			s += " - DONE ";
			SetWindowText(s);
			ctrl->SetPos(100);
			ctrl->KillTimer(m_timerID);	
			_parent->DestroyWindow();
		}
		else {
			s += "- DISCONNECTING ";
			SetWindowText(s);
			ctrl->StepIt();
		}
	}
	else
		CDialog::DestroyWindow();
	
	CDialog::OnTimer(nIDEvent);
}

void CLrsClientDialog::OnDestroy() 
{	
	// TODO: Add your message handler code here	
	this->m_pStatusDialog->DestroyWindow();
	this->m_pLinkProgress->DestroyWindow();
	m_pAlarmDialog[ELECTRONICS_HOUSING]->DestroyWindow();	
	m_pAlarmDialog[SPECTROGRAPH_HOUSING]->DestroyWindow();
	CDialog::OnDestroy();
}
// Change electronic housing housekeeping setpoints
void CLrsClientDialog::OnButtonChangeElecSetpoints() 
{
	m_pAlarmDialog[ELECTRONICS_HOUSING]->ShowWindow(SW_SHOWNORMAL);	//Activates and displays this window
}
// Change spectrometer housing housekeeping setpoints
void CLrsClientDialog::OnButtonChangeSpectSetpoints() 
{
	m_pAlarmDialog[SPECTROGRAPH_HOUSING]->ShowWindow(SW_SHOWNORMAL);	//Activates and displays this window	
}

HBRUSH CLrsClientDialog::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) 
{
int ID;
COLORREF color;
CBrush brush;	
		
	if( nCtlColor == CTLCOLOR_EDIT)
	{	
		ID = pWnd->GetDlgCtrlID();

		switch (ID){
		case IDC_WATER_SENSOR2:
		case IDC_WATER_SENSOR:
			// Status boxes are indexed from IDC_WATER_SENSOR
			color = m_waterAlarmColor[ID - IDC_WATER_SENSOR];
			brush.CreateSolidBrush(color);	
			pDC->SetBkColor(color);
			return brush;		
			break;
		default:
			return CDialog::OnCtlColor(pDC, pWnd, nCtlColor);	
			break;
		}//end switch		
	}

	return CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
}

void CLrsClientDialog::OnShowStatus() 
{
	m_pStatusDialog->ShowWindow(SW_SHOWNORMAL);
	// the window is shown and activated so the focus is taken from the parent window		
}

void CLrsClientDialog::OnReconnectToTarget() 
{
	_theApp->reconnectCORBAClient();	
	// Start timer to update link state
	m_nTimer = SetTimer(1,1000, NULL); //~1 second
	ASSERT(m_nTimer != 0);
}

void CLrsClientDialog::OnTimer(UINT nIDEvent) 
{
	CWnd *pwnd;
		
	m_pLinkIndicator->update();	
	m_pTimeIndicator->update();	

	pwnd = GetDlgItem(IDRECONNECT);
	if(!LrsConnectionStatus::instance()->isConnected()) {
		m_pLinkIndicator->update();	
		pwnd->EnableWindow(TRUE);
		KillTimer(m_nTimer);
		AfxMessageBox("LRS CLIENT disconnected from target");
	}
	else
		pwnd->EnableWindow(FALSE);			

}
