// CPUPAppDlg.cpp : implementation file
//
#include "stdafx.h"
#include "resource.h"
#include "pupappdlg.h"
#include "genoapp.h"
#include <math.h>
#include "dmcwin.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif


/////////////////////////////////////////////////////////////////////////////
// CPUPAppDlg dialog

CPUPAppDlg::CPUPAppDlg(CWnd* pParent, GenoApp *pGenoApp)
	: CDialog(CPUPAppDlg::IDD, pParent)
{
Nat16 i;

	//{{AFX_DATA_INIT(CPUPAppDlg)
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);		
	pTheApp = pGenoApp;

	m_nTimer1 = NULL;
	m_nTimer2 = NULL;
	
	pAM = AlarmManager::instance();
	pCtrl = pTheApp->_pController;
	fMacroDlg = FALSE;
	fFileDlg = FALSE;
	fModelessDlg = FALSE;
	memset(fMotorDlg, FALSE, sizeof(fMotorDlg));
	memset(pMotorDlg, NULL, sizeof(pMotorDlg));

	memcpy(pAxis, pTheApp->_pAxis, sizeof(Axis *)*NUM_AXIS);	
	pMacroProgramDlg = new CMacroProgramDlg(this, pTheApp->_pMacroInterface);
	pFileDlg = new CDatafileDlg(this);	
	pModelessDlg = new CModelessDlg(this, "GENODIALOG");

	for(i=0;i<NUM_AXIS;i++) {
		pMotorDlg[i] = new CMotorDlg(this, pAxis[i],  i);
		pMotorIndicator[i] = 
		new CMotorIndicator(i, pAxis[i], this, IDB_LED_OFF, IDB_LED_ON);
	}

	stopbitmap.LoadBitmap(IDB_STOPBMP);	
}

CPUPAppDlg::~CPUPAppDlg()
{
Nat16 i;

	delete pFileDlg;
	delete pMacroProgramDlg;
	delete pModelessDlg;

	for(i=0;i<NUM_AXIS;i++) {
		delete pMotorDlg[i];	
		delete pMotorIndicator[i];
	}
}
void CPUPAppDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CPUPAppDlg)	
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CPUPAppDlg, CDialog)	
	ON_MESSAGE(WM_MODELESSEXIT, OnModelessExit)		
	ON_MESSAGE(WM_MODELESSOK, OnModelessOk)
	//{{AFX_MSG_MAP(CPUPAppDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_CTLCOLOR()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_WM_TIMER()	
	ON_BN_CLICKED(IDEXIT, OnExit)	
	ON_BN_CLICKED(IDC_RESET, OnControllerReset)
	ON_BN_CLICKED(IDC_SEND, OnSendCtrlCmd)
	ON_BN_CLICKED(ID_FILE, OnFileDlg)	
	ON_BN_CLICKED(ID_PROGRAM, OnProgramDlg)
	ON_BN_CLICKED(ID_Z_MOTOR_DLG, OnZMotorDlg)
	ON_BN_CLICKED(ID_R_MOTOR_DLG, OnRMotorDlg)
	ON_WM_HSCROLL()
	ON_WM_CLOSE()
	ON_WM_LBUTTONUP()
	ON_WM_DESTROY()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CPUPAppDlg message handlers

BOOL CPUPAppDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	UpdateData(FALSE);

	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CPUPAppDlg::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 CPUPAppDlg::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();
	}

	for (int i = 0; i < NUM_AXIS; i++) {
		if (pMotorIndicator[i])
			pMotorIndicator[i]->repaint();

	}
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CPUPAppDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

void CPUPAppDlg::OnTimer(UINT nIDEvent) 
{
CString s;

	if(nIDEvent == 1)// fast updates
		UpdateDisplay(); 
	if(nIDEvent ==2){// slower updates		
		UpdateAlarmDisplay();
	}
}


void CPUPAppDlg::UpdateDisplay()
{
Int32 len = 0;
CString s;

	UpdateMotorStatus();

	//always update time display
	time = CTime::GetCurrentTime();

	s = time.Format( "%H:%M:%S" );
	SetDlgItemText(IDC_TIME, s);
}


void CPUPAppDlg::UpdateStatusWnd(char * text)
{
CEdit *pEdit;
	pEdit = (CEdit*)GetDlgItem(IDC_STATUS);
	pEdit->SetWindowText(text);
}

void CPUPAppDlg::UpdateBitmap(UINT id, CBitmap & bitmap)
{
BITMAP bmp;
CWnd* pWnd;	
CDC* pDC;
CDC DC;

	bitmap.GetBitmap(&bmp);

	pWnd = GetDlgItem(id);
	if(pWnd != NULL && &bmp != NULL)
	{
		pDC = pWnd->GetDC();
		DC.CreateCompatibleDC(pDC);
		DC.SelectObject(bitmap);			
		pDC->BitBlt(0,0,bmp.bmWidth,bmp.bmHeight,&DC, 0, 0, SRCCOPY);
		ReleaseDC(pDC);		
	}
}

void CPUPAppDlg::OnExit() 
{	
	pTheApp->exit();
}

void CPUPAppDlg::OnControllerReset() 
{
	AfxMessageBox("This takes a few seconds");
	pTheApp->initialize();
}

void CPUPAppDlg::UpdateAlarmDisplay()
{
	static Int16 nalarms;

	if(nalarms < pAM->getNumActiveAlarms()) {
		nalarms = pAM->getNumActiveAlarms();	
		pModelessDlg->Create((char *)pAM->getNextActiveAlarmText());
	}
}

void CPUPAppDlg::UpdateMotorStatus()
{
CString s;
Nat16 i;

static Motor::State state[NUM_AXIS];

	for(i=0;i<NUM_AXIS;i++)
	{
		// If jogging or has a state change
		if(pAxis[i]->jogging() 	|| pAxis[i]->state() != state[i]) {		
			pAxis[i]->getStopCodeText(szDataResponse);		
			UpdateStatusWnd(szDataResponse);					
		}

		if (pMotorIndicator[i])
			pMotorIndicator[i]->update();

		state[i] = pAxis[i]->state();
	}

}

void CPUPAppDlg::OnSendCtrlCmd() 
{
	CEdit* pEdit = (CEdit*)GetDlgItem(IDC_COMMAND);
	MotionChannel *c = pCtrl->channel('A'); //pick any axis motion channel
	CDMCWin *servo = (CDMCWin *)c->motiondriver;
	CString TempString;
	pEdit->GetWindowText(TempString);
	servo->Command((char*)((const char*)TempString), szDataResponse, sizeof(szDataResponse));
	UpdateStatusWnd(szDataResponse);		
}


void CPUPAppDlg::OnFileDlg() 
{
	if(!fFileDlg)
	{
		pFileDlg->Create(IDD_FILEDLG, this);
		pFileDlg->ShowWindow(SW_SHOW);
		fFileDlg = TRUE;
	}
}
LRESULT CPUPAppDlg::OnModelessOk(WPARAM wParam, LPARAM lParam)
{
	if(wParam == IDD_MODELESSDIALOG)
	{
		pModelessDlg->DestroyWindow();
		fModelessDlg = FALSE;
	}
	return 0L;
}
LRESULT CPUPAppDlg::OnModelessExit(WPARAM wParam, LPARAM lParam)
{
	if(wParam == IDD_FILEDLG)	
	{
		pFileDlg->DestroyWindow();
		fFileDlg = FALSE;
	}
	if(wParam == IDD_MACROPROGRAM_DLG)	
	{
		pMacroProgramDlg->ShowWindow(SW_HIDE);
		fMacroDlg = FALSE;
	}	
	if(wParam == IDD_MODELESSDIALOG)	
	{
		pModelessDlg->DestroyWindow();
		fModelessDlg = FALSE;
	}
	if(wParam == IDD_MOTOR_DIALOG)	
	{
		pMotorDlg[lParam]->DestroyWindow();
		fMotorDlg[lParam] = FALSE;
	}
	return 0L;
}
void CPUPAppDlg::OnProgramDlg() 
{
	CString initDir("c:\\");
	CFileDialog dlg(TRUE, "macro", "*.txt");
	dlg.m_ofn.lpstrInitialDir = initDir;

	if (dlg.DoModal() != IDOK) 
		return;
	
	// Check for file existence
	FILE *fp;
	if ((fp = fopen(dlg.GetPathName(), "r")) == NULL) {
		char errorBuf[512];
		sprintf(errorBuf, "Couldn't open file \"%s\" for reading",
			dlg.GetPathName());

		pModelessDlg->Create(errorBuf);
		return;
	}
	fclose(fp);

	if(!fMacroDlg)
	{
		if(pMacroProgramDlg->m_hWnd == NULL)
			pMacroProgramDlg->Create(IDD_MACROPROGRAM_DLG, this);

		pMacroProgramDlg->ShowWindow(SW_SHOW);
		fMacroDlg = TRUE;
	}	
	pMacroProgramDlg->SetFile(dlg.GetPathName());	
}


void CPUPAppDlg::OnZMotorDlg() 
{
if(!fMotorDlg[JOINTZ])
{
	pMotorDlg[JOINTZ]->Create(IDD_MOTOR_DIALOG, this);
	pMotorDlg[JOINTZ]->ShowWindow(SW_SHOW);	
	fMotorDlg[JOINTZ] = TRUE;
}		

}

void CPUPAppDlg::OnRMotorDlg() 
{
if(!fMotorDlg[JOINTR])
{
	pMotorDlg[JOINTR]->Create(IDD_MOTOR_DIALOG, this);
	pMotorDlg[JOINTR]->ShowWindow(SW_SHOW);	
	fMotorDlg[JOINTR] = TRUE;
}			
}

void CPUPAppDlg::StartTimers()
{
	// Display the controller version information
	char szVersion[128];
	CString TempString;
#ifdef GALIL_CONTROL
	CDMCWinRegistry DMCWinRegistry;
	GALILREGISTRY galilregistry;
	// Is the controller registered?
	if (DMCWinRegistry.GetGalilRegistryInfo(1, &galilregistry) != 0)	
		UpdateStatusWnd("Could not find controller in the Windows registry");		
#endif
	if (pCtrl->isConnected())
	{
		if (pCtrl->getVersion(szVersion, sizeof(szVersion)) == 0)
			UpdateStatusWnd(szVersion);			
		if(m_nTimer1 == NULL)	{
			m_nTimer1 = SetTimer(1,MOTOR_SAMPLE_PERIOD/2,NULL);		
			ASSERT(m_nTimer1 != 0);
		}
		if(m_nTimer2 == NULL)	{
			m_nTimer2 = SetTimer(2,1000,NULL); //~1 sec
			ASSERT(m_nTimer2 != 0);
		}
	}
	else
	{
	// Report error
		UpdateStatusWnd("Not connected with controller");
	}

}
