// VIBFinderDlg.cpp : implementation file
//

#include "stdafx.h"
#include "VIBFinder.h"
#include "VIBFinderDlg.h"
#include "ActionDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#include <fcntl.h>
#include <io.h>
#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	
	virtual BOOL OnInitDialog();

// Implementation
protected:
	DECLARE_MESSAGE_MAP()
};

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

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

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

	//VersionText eintragen
	char ProgrammVersion[128];
	char TempText[256];
	if( CVIBFinderDlg::GetVersion(ProgrammVersion) == 0){
		sprintf_s(TempText,sizeof(TempText),"VIBFinder %s",ProgrammVersion);
		CWnd * plblText = CDialog::GetDlgItem(IDC_ABOUT_TEXT);
		CStatic *p = (CStatic *) plblText;
		p->SetWindowTextA(TempText);
		//SendDlgItemMessage(IDC_ABOUT_TEXT, WM_SETTEXT ,0,(LPARAM)"Hallo");// geht auch
	}

	return TRUE;	
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
END_MESSAGE_MAP()


// CVIBFinderDlg dialog


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

	// Create TcpDisplay.jar
	HRSRC hResource = FindResource(NULL, (char *)IDR_TCPDISPLAY_JAR, "RT_CUSTOM");
	if (hResource == NULL)
		return;
	char *pData = (char *)LockResource(LoadResource(NULL, hResource));
	int size = SizeofResource(NULL, hResource);
	m_pTcpDisplayFileName = _tempnam(NULL, "TcpDisplay");
	if (!m_pTcpDisplayFileName)
		return;
	FILE *pFile;
	if (fopen_s(&pFile, m_pTcpDisplayFileName, "wb") != 0)
		return;
	fwrite(pData, 1, size, pFile);
	fclose(pFile);
}

/////////////////////////////////////////////////////////////////////////////
void CVIBFinderDlg::OnCancel()
/////////////////////////////////////////////////////////////////////////////
{
	if (m_pTcpDisplayFileName)
	{
		remove(m_pTcpDisplayFileName);
		free(m_pTcpDisplayFileName);
		m_pTcpDisplayFileName = NULL;
	}
	ClearDeviceList();
	CDialog::OnCancel();
}

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

BEGIN_MESSAGE_MAP(CVIBFinderDlg, CDialog)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	//}}AFX_MSG_MAP
	ON_BN_CLICKED(IDC_FINDDEV, &CVIBFinderDlg::OnBnClickedFinddev)
	ON_BN_CLICKED(IDC_OPENDEV, &CVIBFinderDlg::OnBnClickedOpendev)
	ON_MESSAGE(IDM_TSKREADY,&CVIBFinderDlg::OnReadyTsk)
	ON_WM_SETCURSOR()
	ON_NOTIFY(NM_DBLCLK, IDC_DEVLIST, &CVIBFinderDlg::OnDblClkDevList)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CVIBFinderDlg message handlers
/////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////
//!Hier läuft die Nachricht vom Thread auf
/////////////////////////////////////////////////////////////////////////////
LRESULT CVIBFinderDlg::OnReadyTsk(WPARAM wParam, LPARAM lParam)
/////////////////////////////////////////////////////////////////////////////
{
	CListCtrl *pLC = (CListCtrl*)GetDlgItem(IDC_DEVLIST);
	int size0, size1;

	pLC->DeleteAllItems();

	//Füllt die Informationen ins Form
	char Text[64];
	vector <iVIBBox*>::iterator pIter;
	for (pIter = m_DeviceList.begin(); pIter < m_DeviceList.end(); pIter++)
	{
		int listIndex = pLC->GetItemCount();

		in_addr adr;
		adr.S_un.S_addr = (*pIter)->Get_IpAddr();
		pLC->InsertItem(listIndex, inet_ntoa(adr));

		pLC->SetItemText(listIndex, 1, (*pIter)->Get_Description());

		if ((*pIter)->Get_Feature() & 0x40)
		{
			unsigned char mac[6];
			(*pIter)->Get_MacAddress(mac);
			sprintf_s(Text, sizeof(Text), "%02X-%02X-%02X-%02X-%02X-%02X",
						mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
			pLC->SetItemText(listIndex, 2, Text);
		}
	}

	pLC->SetColumnWidth(0, LVSCW_AUTOSIZE);
	size0 = pLC->GetColumnWidth(0);
	pLC->SetColumnWidth(0, LVSCW_AUTOSIZE_USEHEADER);
	size1 = pLC->GetColumnWidth(0);
	if (size0 > size1)
		pLC->SetColumnWidth(0, LVSCW_AUTOSIZE);

	pLC->SetColumnWidth(1, LVSCW_AUTOSIZE);
	size0 = pLC->GetColumnWidth(1);
	pLC->SetColumnWidth(1, LVSCW_AUTOSIZE_USEHEADER);
	size1 = pLC->GetColumnWidth(1);
	if (size0 > size1)
		pLC->SetColumnWidth(1, LVSCW_AUTOSIZE);

	pLC->SetColumnWidth(2, LVSCW_AUTOSIZE);
	size0 = pLC->GetColumnWidth(2);
	pLC->SetColumnWidth(2, LVSCW_AUTOSIZE_USEHEADER);
	size1 = pLC->GetColumnWidth(2);
	if (size0 > size1)
		pLC->SetColumnWidth(2, LVSCW_AUTOSIZE);

	//gibt es Elemente
	if(m_DeviceList.size() >0)
	{
//		pLB->SetCurSel(0);
		GetDlgItem(IDC_OPENDEV)->EnableWindow(TRUE);
	}

	//suchen wieder erlauben
	GetDlgItem(IDC_FINDDEV)->EnableWindow(TRUE);
	m_ChangeCursor = TRUE;
	SetCursor(LoadCursor(NULL, IDC_ARROW));

	return 0;
}

/////////////////////////////////////////////////////////////////////////////
BOOL CVIBFinderDlg::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
/////////////////////////////////////////////////////////////////////////////
{
	if (m_ChangeCursor)
	{
		return CDialog::OnSetCursor(pWnd, nHitTest, message);
	}
	else
		return TRUE;
}

/////////////////////////////////////////////////////////////////////////////
BOOL CVIBFinderDlg::OnInitDialog()
/////////////////////////////////////////////////////////////////////////////
{
	HFONT fCourier;
	LOGFONT lf;

	CDialog::OnInitDialog();

#ifdef _DEBUG
	AllocConsole();
	int hCrt, i;
	FILE *hf;
	hCrt = _open_osfhandle((long)GetStdHandle(STD_OUTPUT_HANDLE), _O_TEXT);
	hf = _fdopen( hCrt, "w" );
	*stdout = *hf;
	i = setvbuf( stdout, NULL, _IONBF, 0 );
#endif

	//VersionText eintragen
	char ProgrammVersion[128];
	char TempText[256];
	if( GetVersion(ProgrammVersion) == 0)
	{
		sprintf_s(TempText, sizeof(TempText), "VIBFinder %s", ProgrammVersion);
		CWnd::SetWindowTextA(TempText);
	}

	// 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 strMenu;
		strMenu.LoadString(IDS_ABOUTBOX);
		if (!strMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strMenu);
		}
//		strMenu.LoadStringA(IDS_CLEARTEXT);
//		if (!strMenu.IsEmpty())
//			pSysMenu->AppendMenu(MF_STRING, IDM_CLEARTEXT, strMenu);
	}

	// 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

	WORD wVersionRequested;
	WSADATA wsaData;
	int err;

	wVersionRequested = MAKEWORD(2, 2);
	err = WSAStartup(wVersionRequested, &wsaData);

	ClearDeviceList();
	m_bSendFlag = true;
	m_ChangeCursor = true;

	// Generate font
	memset(&lf, 0, sizeof(LOGFONT)); // zero out font structure
	lf.lfHeight = 14;
	lf.lfWeight = FW_NORMAL;
	strcpy_s(lf.lfFaceName, 32, "Courier New");
	fCourier = CreateFontIndirect(&lf);

	// Setup ListCtrl for dvice list
	CListCtrl *pLC = (CListCtrl*)GetDlgItem(IDC_DEVLIST);
	pLC->SetExtendedStyle(pLC->GetExtendedStyle() | LVS_EX_FULLROWSELECT);
	LVCOLUMN col;
	col.mask = LVCF_TEXT;
	col.fmt = LVCFMT_LEFT;
	col.cx = LVSCW_AUTOSIZE_USEHEADER;
	col.pszText = "IP Address";
	col.cchTextMax = (int)strlen(col.pszText)+1;
	col.iSubItem = 0;
	col.iImage = 0;
	col.iOrder = 0;
	pLC->InsertColumn(0, &col);
	col.pszText = "Description";
	col.cchTextMax = (int)strlen(col.pszText)+1;
	pLC->InsertColumn(1, &col);
	col.pszText = "MAC Address";
	col.cchTextMax = (int)strlen(col.pszText)+1;
	pLC->InsertColumn(2, &col);
	pLC->SetColumnWidth(0, LVSCW_AUTOSIZE_USEHEADER);
	pLC->SetColumnWidth(1, LVSCW_AUTOSIZE_USEHEADER);
	pLC->SetColumnWidth(2, LVSCW_AUTOSIZE_USEHEADER);

	m_hReceiveThread = ::CreateThread(NULL, NULL, TskReceiveUDP,
		(LPVOID)this, NULL, &m_dwThreadID);

	return TRUE;  // return TRUE  unless you set the focus to a control
}

/////////////////////////////////////////////////////////////////////////////
void CVIBFinderDlg::OnSysCommand(UINT nID, LPARAM lParam)
/////////////////////////////////////////////////////////////////////////////
{
	if (nID == 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 CVIBFinderDlg::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 CVIBFinderDlg::OnQueryDragIcon()
/////////////////////////////////////////////////////////////////////////////
{
	return static_cast<HCURSOR>(m_hIcon);
}

////////////////////////////////////////////////////////////////////////////
void CVIBFinderDlg::OnBnClickedFinddev()
/////////////////////////////////////////////////////////////////////////////
{
	// Liste löschen 
	ClearDeviceList();

	// erneutes suchen verhindern (solange die Suche noch läuft)
	GetDlgItem(IDC_FINDDEV)->EnableWindow(false);
	SetCursor(LoadCursor(NULL, IDC_WAIT) );
	m_ChangeCursor = false;

	m_bSendFlag = true;
}

/////////////////////////////////////////////////////////////////////////////
void CVIBFinderDlg::OnBnClickedOpendev()
/////////////////////////////////////////////////////////////////////////////
{
	CString Text, IP, Serial;
	CListCtrl *pLC = (CListCtrl*)GetDlgItem(IDC_DEVLIST);
	pLC->GetSelectionMark();
	int index = pLC->GetSelectionMark();

	if (index < 0 || pLC->GetSelectedCount() != 1)
	{
		AfxMessageBox("Select a device first!");
		return;
	}

	if (m_DeviceList[index]->Get_bGotFeature()== false)
	{
		if (m_DeviceList[index]->Get_Feature())
		{
			AfxMessageBox("No answer from device!");
			return;
		}
	}

	CActionDlg oDlg;
	in_addr adr;
	adr.S_un.S_addr = m_DeviceList[index]->Get_IpAddr();
	oDlg.m_IP = inet_ntoa(adr);
	oDlg.m_Subnet = m_DeviceList[index]->Get_IpSubnet();
	oDlg.m_Description = m_DeviceList[index]->Get_Description();
	if (m_DeviceList[index]->Get_Feature() & 0x40)
	{
		unsigned char mac[6];
		m_DeviceList[index]->Get_MacAddress(mac);
		oDlg.m_MacAddress.Format("%02X-%02X-%02X-%02X-%02X-%02X",
					mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
	}
	oDlg.m_piVIBBox = m_DeviceList[index];
	oDlg.m_pParam = (LPVOID)this;
	oDlg.m_pTcpDisplayFileName = m_pTcpDisplayFileName;
	if (oDlg.DoModal() == IDOK)
	{
	}
	if (oDlg.m_bResetDev)
	{
		m_DeviceList[index]->ResetDevice();
		ClearDeviceList();
	}
}

/////////////////////////////////////////////////////////////////////////////
void CVIBFinderDlg::OnDblClkDevList(NMHDR *pNMHDR, LRESULT *pResult)
/////////////////////////////////////////////////////////////////////////////
{
	CListCtrl *pLC = (CListCtrl*)GetDlgItem(IDC_DEVLIST);
	if (pLC->GetSelectionMark() >= 0 && pLC->GetSelectedCount() == 1)
		OnBnClickedOpendev();
	*pResult = 0;
}

/////////////////////////////////////////////////////////////////////////////
//! \brief Check UDP
/////////////////////////////////////////////////////////////////////////////
DWORD WINAPI CVIBFinderDlg::TskReceiveUDP(LPVOID pParam)
/////////////////////////////////////////////////////////////////////////////
{
	CVIBFinderDlg *pDlg = (CVIBFinderDlg*)pParam;

	while (true)
	{
		// soll neu gesucht werden?
		if (pDlg->m_bSendFlag)
		{
			pDlg->m_bSendFlag = false;

			// Jetzt suchen
			VIBBox::Discover(&pDlg->m_DeviceList);
			FlashBox::Discover(&pDlg->m_DeviceList);

			// MFC ist ->nicht<- thread safe
			// Nachricht senden (nicht warten)
			::PostMessage(pDlg->m_hWnd, IDM_TSKREADY, 0, 0);
		}
		else
			Sleep(100);
	}
}

/////////////////////////////////////////////////////////////////////////////
//! \brief Clear device list
/////////////////////////////////////////////////////////////////////////////
void CVIBFinderDlg::ClearDeviceList()
/////////////////////////////////////////////////////////////////////////////
{
	//Liste löschen
	CListCtrl *pLC = (CListCtrl*)GetDlgItem(IDC_DEVLIST);
	pLC->DeleteAllItems();

	GetDlgItem(IDC_OPENDEV)->EnableWindow(false);

	// Alle Elemente löschen
	vector <iVIBBox*>::iterator pIter;
	for (int i= (int)m_DeviceList.size() -1 ; i>=0; i--)
	{
		pIter = m_DeviceList.begin();
		pIter += i;

		// free obj
		delete(*pIter);

		// free the item
		m_DeviceList.erase(pIter);
	}
}

/////////////////////////////////////////////////////////////////////////////
int CVIBFinderDlg::GetVersion(char ProgrammVersion[128])
/////////////////////////////////////////////////////////////////////////////
{
	CHAR Text[512];
	ProgrammVersion[0]=0;

	try
	{
		//Name und Pfad der exe
		CHAR ModuleFileName[256];
		if (GetModuleFileName(NULL, ModuleFileName, sizeof(ModuleFileName)) == 0)
			return -1;
		sprintf_s(Text, sizeof(Text), "ModuleFileName: %s\n", ModuleFileName);

		//wie groß ist die Version?
		DWORD Dummy=0;
		DWORD InfoSize = GetFileVersionInfoSize(ModuleFileName, &Dummy);
		if (InfoSize == 0)
			return -1;
		sprintf_s(Text, sizeof(Text), "InfoSize: %d\n", InfoSize);
		
		//VersionsInfo auslesen
		char *pInfoBuffer = new char[InfoSize];
		if (GetFileVersionInfo(ModuleFileName, NULL, InfoSize, pInfoBuffer) ==0)
			return -1;

		//Jetzt die Version
		VS_FIXEDFILEINFO *pFixedData;
		UINT InfoLen;
		if (VerQueryValue(pInfoBuffer, "\\",(void**)&pFixedData, &InfoLen)!=0)
		{
			sprintf_s(ProgrammVersion, 128, "%d.%d.%d.%d",
				 HIWORD(pFixedData->dwProductVersionMS), LOWORD(pFixedData->dwProductVersionMS),
				 HIWORD(pFixedData->dwProductVersionLS), LOWORD(pFixedData->dwProductVersionLS));
			delete [] pInfoBuffer;
		}
		else
		{
			delete [] pInfoBuffer;
			return -1;
		}
	}
	catch(...)
	{
		return -1;
	}

	return 0;
}

/////////////////////////////////////////////////////////////////////////////
