// HYKBStatsDemoDlg.cpp : implementation file
//

#include "stdafx.h"
#include "HYKBStatsDemo.h"
#include "HYKBStatsDemoDlg.h"
#include <string>
#include "HYKBStatsAPI.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// Dialog Data
	enum { IDD = IDD_ABOUTBOX };

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support

// Implementation
protected:
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
END_MESSAGE_MAP()


// CHYKBStatsDemoDlg dialog




CHYKBStatsDemoDlg::CHYKBStatsDemoDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CHYKBStatsDemoDlg::IDD, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CHYKBStatsDemoDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CHYKBStatsDemoDlg, CDialog)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_WM_CLOSE() 
	//}}AFX_MSG_MAP
	ON_BN_CLICKED(IDC_ISUSBCONNECT, &CHYKBStatsDemoDlg::OnBnClickedIsusbconnect)
	ON_BN_CLICKED(IDC_FLUSHDATA, &CHYKBStatsDemoDlg::OnBnClickedFlushdata)
	ON_BN_CLICKED(IDC_KEYBOARDMODEL, &CHYKBStatsDemoDlg::OnBnClickedKeyboardmodel)
	ON_BN_CLICKED(IDC_GETSWIPECOUNT, &CHYKBStatsDemoDlg::OnBnClickedGetswipecount)
	ON_BN_CLICKED(IDC_MAXCOUNT, &CHYKBStatsDemoDlg::OnBnClickedMaxcount)
	ON_BN_CLICKED(IDC_PRESSCOUNT, &CHYKBStatsDemoDlg::OnBnClickedPresscount)
	ON_BN_CLICKED(IDC_FIRMWARE, &CHYKBStatsDemoDlg::OnBnClickedFirmware)
	ON_BN_CLICKED(IDC_USBFIRMWARE, &CHYKBStatsDemoDlg::OnBnClickedUsbfirmware)
	ON_BN_CLICKED(IDC_KEYMAP, &CHYKBStatsDemoDlg::OnBnClickedKeymap)
	ON_BN_CLICKED(IDC_GETRESULTOFUPDATE, &CHYKBStatsDemoDlg::OnBnClickedGetresultofupdate)
	ON_BN_CLICKED(IDC_PS2FIRMWARE, &CHYKBStatsDemoDlg::OnBnClickedPs2firmware)
END_MESSAGE_MAP()


// CHYKBStatsDemoDlg message handlers

afx_msg void CHYKBStatsDemoDlg::OnClose()
{
	TRACE("Close the window");
	//Flush the data every time to close the program
	OnBnClickedFlushdata();
	PostQuitMessage(0);
}

BOOL CHYKBStatsDemoDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// 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);
		}
	}

	// 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 CHYKBStatsDemoDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		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 CHYKBStatsDemoDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<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 function to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CHYKBStatsDemoDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}

CString CHYKBStatsDemoDlg::GetReturnStatus(int status)
{
	CString str;
	str.Empty();
	switch(status)
	{
		case 0x00:
			str = _T("Operation Success");		
		break;
		case 0x01:
			str = _T("The system is out of memory");		
		break;
		case 0x60:
			str = _T("Cannot create file");		
		break;
		case 0x61:
			str = _T("Cannot open file");		
		break;
		case 0x62:
			str = _T("Invalid exe file");		
		break;
		case 0x63:
			str = _T("exe file cannot be found");		
		break;
		case 0x64:
			str = _T("exe path is not found");		
		break;
		case 0xF0:
			str = _T("Checksum error");
		break;
		case 0xF1:
			str= _T("Invalid command");
		break;		
		case 0xFB:
			str= _T("Length error");
		break;
		case 0xFF:
			str= _T("Command error");
		break;
		case 0xE1:
			str = _T("Initial USB keyboard fail");
		break;
		case 0xE2:
			str = _T("Send command fail");
		break;
		case 0x2F:
			str = _T("Keyboard model is not found");
		break;
		case 0x2E:
			str = _T("No Key Index found");
		break;
		case 0xE6:
			str = _T("Invalid input parameters");
		break;
		case 0xE7:
			str = _T("Received command fail");
		break;
		default:
			str.Format("Operation error, 0x%x",status);
		break;

	};

	
	return str;
}

void CHYKBStatsDemoDlg::SetCommandStatus(int cmd,int status)
{
	CString str;

	switch(cmd)
	{
		case GET_PID_COMMAND:
			str.Format("Get PID command, %s",GetReturnStatus(status));
		break;
		case GET_KEY_PRESSDOWN_COUNT_COMMAND:
			str.Format("Key press count command, %s",GetReturnStatus(status));
		break;
		case GET_KEY_PRESSDOWN_COUNTWITHMAX_COMMAND:
			str.Format("Get Max count command, %s",GetReturnStatus(status));
		break;
		case GET_MSRGOODBAD_COUNT_COMMAND:
			str.Format("Get MSR command, %s",GetReturnStatus(status));
		break;
		case GET_FIRMWARE_COMMAND:
			str.Format("Firmware version : %s",GetReturnStatus(status));
		break;
		default:
			break;
	}
	if(!str.IsEmpty())
		AfxMessageBox(str);

}

void CHYKBStatsDemoDlg::OnBnClickedIsusbconnect()
{
	// TODO: Add your control notification handler code here
	if(IsUsbConnected())
		GetDlgItem(IDC_USBPS2)->SetWindowText("USB connected");
		//AfxMessageBox("Heng Yu USB Keyboard is connected");
	else
		GetDlgItem(IDC_USBPS2)->SetWindowText("PS2 connected");
		//AfxMessageBox("Heng Yu USB Keyboard is not connected. Assume PS/2 Keyboard is connected");
}

void CHYKBStatsDemoDlg::OnBnClickedFlushdata()
{
	// TODO: Add your control notification handler code here
	if(!FlushKbEEPROM())
		AfxMessageBox("Flush data to Keyboard EERPOM successfully");
	else
		AfxMessageBox("Flush data to Keyboard EERPOM failed");
			
}

void CHYKBStatsDemoDlg::OnBnClickedKeyboardmodel()
{
	// TODO: Add your control notification handler code here
	model_prop *pModel;
	CString str;
	int ret=0;

	pModel = (model_prop *)calloc(1,sizeof(model_prop));
	if(pModel)
	{
		ret = GetKbModel(pModel);
		SetCommandStatus(GET_PID_COMMAND,ret);
		if(ret == 0)
		{
			str.Format("Product ID : %s",pModel->sModelName);
			GetDlgItem(IDC_OUTPUT)->SetWindowText(str.GetBuffer());
		}
		free(pModel);
	}
}

void CHYKBStatsDemoDlg::OnBnClickedGetswipecount()
{
	// TODO: Add your control notification handler code here
	int nTotalCount=0,nSuccessCount=0;
	int ret=0;
	CString str;
	ret = GetSwipeCount(&nTotalCount,&nSuccessCount);
	SetCommandStatus(GET_MSRGOODBAD_COUNT_COMMAND,ret);
	if(ret ==0)
	{
		str.Format("Total swipe : %d  \r\nGood swipe : %d   \r\nBad swipe : %d",
			nTotalCount,nSuccessCount,(nTotalCount-nSuccessCount));
		GetDlgItem(IDC_OUTPUT)->SetWindowText(str.GetBuffer());
	}

}

void CHYKBStatsDemoDlg::OnBnClickedMaxcount()
{
	int nKeyPos=0,nCount=0,ret=0;
	CString str;
	model_prop modelProp;
	ret = GetKbModel(&modelProp);
	if(ret == 0)
	{
		ret = GetMaxPressedCount(&nKeyPos,&nCount);
		SetCommandStatus(GET_KEY_PRESSDOWN_COUNTWITHMAX_COMMAND,ret);
		if(ret == 0)
		{
			str.Format("Key position : %d, Max Count : %d",
			nKeyPos,nCount);
			GetDlgItem(IDC_OUTPUT)->SetWindowText(str.GetBuffer());
		}
	}
	else
		SetCommandStatus(GET_PID_COMMAND,ret);
}

void CHYKBStatsDemoDlg::OnBnClickedPresscount()
{
	// TODO: Add your control notification handler code here
	int nCount=0,ret=0;
	CString str,str1;
	model_prop modelProp;
	//save in key count file
	CFile file;
	CString filename="keycount.sav";
	ret = GetKbModel(&modelProp);
	if(ret == 0)
	{

		if(file.Open(filename,CFile::modeWrite|CFile::modeCreate))
		{
			for(int i=0;i<modelProp.nTotalKeys;i++)
			{
				str1.Format("Getting key[%d] count",i);
				GetDlgItem(IDC_OUTPUT)->SetWindowText(str1);
				ret = GetPressedCount(modelProp.pbKeyIndex[i],&nCount);
				if(ret == 0)
				{
					str.Format("Key Pos : %02d, Key Index : 0x%02x, Count : %02d\n",
					i,modelProp.pbKeyIndex[i],nCount);
					file.Write(str,str.GetLength());
				}
				else
				{
					SetCommandStatus(GET_KEY_PRESSDOWN_COUNT_COMMAND,ret);
					break;
				}
				//add some delays is better
				//Sleep(10);
			}
			file.Close();
			GetDlgItem(IDC_OUTPUT)->SetWindowText("");
			AfxMessageBox("Get Press Count success. Save in keycount.sav");
		}
	}
	else
		SetCommandStatus(GET_PID_COMMAND,ret);
}

void CHYKBStatsDemoDlg::OnBnClickedFirmware()
{
	// TODO: Add your control notification handler code here
	int nCount=0,ret=0;
	CString str,str1;
	str.GetBuffer(25);

	ret = GetFirmware((char *)str.GetBuffer());
	if(ret == 0)
	{
		str1.Format("Firmware version : %s",str.GetBuffer());
		GetDlgItem(IDC_OUTPUT)->SetWindowText(str1);
		str.ReleaseBuffer();
	}
	SetCommandStatus(GET_FIRMWARE_COMMAND,ret);
}

void CHYKBStatsDemoDlg::OnBnClickedUsbfirmware()
{
	// TODO: Add your control notification handler code here
	CString program,bin,log,str;
	
	TCHAR currentDir[MAX_PATH]={0};
	int ret=0,retry=0;
	char content[2048]={0};
	time_t time;
	CFileStatus status;
	//get current directory
	GetCurrentDirectory(MAX_PATH, currentDir);
	//example, set the path of program that can be found
	program.Format("%s\\%s",currentDir,"HY_USB_FD.exe");
	//example, set the path of bin file that can be found
	bin.Format("%s\\%s",currentDir,"L2326V152.bin");
	//example, set the path of log file that can be created
	log.Format("%s\\%s",currentDir,"USBFirmwareLog.txt");
	
	//remove the previous log file before
	if(CFile::GetStatus(log.GetBuffer(),status))
		CFile::Remove(log.GetBuffer());

	if(!UpdateFirmware(program.GetBuffer(),bin.GetBuffer(),log.GetBuffer()))
	{
		GetDlgItem(IDC_OUTPUT)->SetWindowText("Update Firmware processing ...\r\n");
		GetDlgItem(IDC_OUTPUT)->UpdateWindow();
		//check the log file has been created or not
		do
		{
			ret = GetResultofUpdate(log.GetBuffer(),content,&time);
			if(ret == 0)
			{
				//get the content of the log file
				str.Format("Content : %s \r\nLatest Mod Time: %s\r\n",content,ctime(&time));
				GetDlgItem(IDC_OUTPUT)->SetWindowText(str);
				break;
			}
			//delay 1s if not found
			Sleep(1000);
			retry++;
		}while(ret != 0 || retry < 120); // usb within 2 min

	}
	else
	{
		AfxMessageBox("Update Firmware through USB fail");
	}

}

void CHYKBStatsDemoDlg::OnBnClickedKeymap()
{
	// TODO: Add your control notification handler code here
	/*
	CString program,bin,log;
	TCHAR currentDir[MAX_PATH]={0};
	GetCurrentDirectory(MAX_PATH, currentDir );
	program.Format("%s%\\s",currentDir,"HY_USB_FD.exe");
	bin.Format("%s%\\s",currentDir,"L2326V152.bin");
	log.Format("%s%\\s",currentDir,"log.txt");
	if(UpdateKeyMap(program.GetBuffer(),bin.GetBuffer(),log.GetBuffer()))
		AfxMessageBox("Update KeyMap successfully");
	else
		AfxMessageBox("Update KeyMap fail");
		*/
	// TODO: Add your control notification handler code here
	CString program,bin,log,str;
	
	TCHAR currentDir[MAX_PATH]={0};
	int ret=0,retry=0;
	char content[2048]={0};
	time_t time;
	CFileStatus status;
	//get current directory
	GetCurrentDirectory(MAX_PATH, currentDir);
	//Example. set the path of program that can be found
	program.Format("%s\\%s",currentDir,"KeymapDownloader2.exe");
	//Example. set the path of bin file that can be found
	bin.Format("%s\\%s",currentDir,"keymap.dat");
	//Example. set the path of log file that can be created
	log.Format("%s\\%s",currentDir,"keymaplog.txt");
	
	//remove the previous log file before
	if(CFile::GetStatus(log.GetBuffer(),status))
		CFile::Remove(log.GetBuffer());

	if(!UpdateKeyMap(program.GetBuffer(),bin.GetBuffer(),log.GetBuffer()))
	{
		GetDlgItem(IDC_OUTPUT)->SetWindowText("Update KeyMap processing ...\r\n");
		GetDlgItem(IDC_OUTPUT)->UpdateWindow();

		do
		{
			ret = GetResultofUpdate(log.GetBuffer(),content,&time);
			if(ret == 0)
			{
				str.Format("Content : %s \r\nLatest Mod Time: %s\r\n",content,ctime(&time));
				GetDlgItem(IDC_OUTPUT)->SetWindowText(str);
				break;
			}
			Sleep(1000);
			retry++;
		}while(ret != 0 || retry < 180); // within 3 min

	}
	else
	{
		AfxMessageBox("Update Firmware fail");
	}

}

void CHYKBStatsDemoDlg::OnBnClickedGetresultofupdate()
{
	// TODO: Add your control notification handler code here
	CString log,str;
	time_t time;
	char content[2048]={0};
	//get current directory
	TCHAR currentDir[MAX_PATH]={0};
	GetCurrentDirectory(MAX_PATH, currentDir );
	log.Format("%s\\%s",currentDir,"log.txt");

	if(!GetResultofUpdate(log.GetBuffer(),content,&time))
	{
		str.Format("Content : %s \r\nLatest Mod Time: %s\r\n",content,ctime(&time));
		GetDlgItem(IDC_OUTPUT)->SetWindowText(str);
		AfxMessageBox("Get result of update successfully");
	}
	else
		AfxMessageBox("Get result of update fail");

}

void CHYKBStatsDemoDlg::OnBnClickedPs2firmware()
{
	// TODO: Add your control notification handler code here
	CString program,bin,log,str;
	CFile file;
	TCHAR currentDir[MAX_PATH]={0};
	int ret=0,retry=0;
	char content[2048]={0};
	time_t time;
	CFileStatus status;
	//get current directory
	GetCurrentDirectory(MAX_PATH, currentDir);
	//Example. set the path of program that can be found
	program.Format("%s\\%s",currentDir,"HY_PS2_FD.exe");
	//Example. set the path of bin file that can be found
	bin.Format("%s\\%s",currentDir,"L2326V151.bin");
	//Example. set the path of log file that can be created
	log.Format("%s\\%s",currentDir,"PS2FirmwareLog.txt");
	
	//remove the previous log file before
	file.SetFilePath(log.GetBuffer());
	//if(file.GetStatus())
	if(CFile::GetStatus(log.GetBuffer(),status))
		file.Remove(log.GetBuffer());

	if(!UpdateFirmware(program.GetBuffer(),bin.GetBuffer(),log.GetBuffer()))
	{
		GetDlgItem(IDC_OUTPUT)->SetWindowText("Update Firmware processing ...\r\n");
		GetDlgItem(IDC_OUTPUT)->UpdateWindow();
		do
		{
			ret = GetResultofUpdate(log.GetBuffer(),content,&time);
			//return success
			if(ret == 0)
			{
				str.Format("Content : %s \r\nLatest Mod Time: %s\r\n",content,ctime(&time));
				GetDlgItem(IDC_OUTPUT)->SetWindowText(str);
				break;
			}
			Sleep(1000);
			retry++;
		}while(ret != 0 || retry < 420); // PS2 within 5 min

	}
	else
	{
		AfxMessageBox("Update Firmware through PS2 fail");
	}

}

