// Rj45Thread.cpp : implementation file
//

#include "stdafx.h"
#include "Rj45Thread.h"

#include "Global.h"

#ifdef _DEBUG
//#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

HANDLE CRj45Thread::m_hEventThreadKilled;
HANDLE CRj45Thread::m_hEventProtocol;

/////////////////////////////////////////////////////////////////////////////
// CRj45Thread

IMPLEMENT_DYNCREATE(CRj45Thread, CWinThread)

CRj45Thread::CRj45Thread()
{
}

CRj45Thread::~CRj45Thread()
{
}

void CRj45Thread::operator delete(void* p)
{
	// The exiting main application thread waits for this event before completely
	// terminating in order to avoid a false memory leak detection. 

	CWinThread::operator delete(p);
	SetEvent(m_hEventThreadKilled);
}

BOOL CRj45Thread::InitInstance()
{
	if (m_wndRj45.Create() == FALSE)
		return FALSE;

	// It is important to set CWinThread::m_pMainWnd to the user interface
	// window.  This is required so that when the m_pMainWnd is destroyed,
	// the CWinThread is also automatically destroyed.  For insight into
	// how the CWinThread is automatically destroyed when the m_pMainWnd
	// window is destroyed, see the implementation of CWnd::OnNcDestroy
	// in wincore.cpp of the MFC sources.

	m_pMainWnd = &m_wndRj45;
//	SetThreadPriority(THREAD_PRIORITY_ABOVE_NORMAL);
	return TRUE;
}

int CRj45Thread::ExitInstance()
{
	// TODO:  perform any per-thread cleanup here
	return CWinThread::ExitInstance();
}

void CRj45Thread::PrepareEvent()
{
	m_hEventThreadKilled = CreateEvent(NULL, FALSE, FALSE, NULL); 
	m_hEventProtocol = CreateEvent(NULL, FALSE, FALSE, NULL); 
}

void CRj45Thread::UnprepareEvent()
{
	CloseHandle(m_hEventThreadKilled);
	CloseHandle(m_hEventProtocol);
}

BEGIN_MESSAGE_MAP(CRj45Thread, CWinThread)
	//{{AFX_MSG_MAP(CRj45Thread)
		// NOTE - the ClassWizard will add and remove mapping macros here.
	//}}AFX_MSG_MAP
#if _MSC_VER >= 1300
	ON_THREAD_MESSAGE(WM_RJ45_DISCONNECT, OnDisconnect)
	ON_THREAD_MESSAGE(WM_RJ45_DATA, OnData)
	ON_THREAD_MESSAGE(WM_RJ45_ERASE_PAGE, OnErasePage)
	ON_THREAD_MESSAGE(WM_RJ45_BEGIN_READ, OnBeginRead)
#else
	ON_MESSAGE(WM_RJ45_DISCONNECT, OnDisconnect)
	ON_MESSAGE(WM_RJ45_DATA, OnData)
	ON_MESSAGE(WM_RJ45_ERASE_PAGE, OnErasePage)
	ON_MESSAGE(WM_RJ45_BEGIN_READ, OnBeginRead)
#endif
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CRj45Thread message handlers

void CRj45Thread::OnDisconnect(WPARAM, LPARAM)
{
	m_wndRj45.DestroyWindow();
}

void CRj45Thread::OnData(WPARAM wParam, LPARAM lParam)
{
	m_wndRj45.m_tcp.Write((char *)lParam, (int)wParam);
}

void CRj45Thread::OnBeginRead(WPARAM wParam, LPARAM lParam)
{
	BOOL bBegin = (BOOL)wParam;
	char * p = (char *)lParam;
	if (bBegin)
	{
		m_wndRj45.BeginSavingFile(p);
	}
	else
	{
		m_wndRj45.EndSavingFile();
	}
}

void CRj45Thread::OnErasePage(WPARAM wParam, LPARAM)
{
	char iPFlashPage = (char)wParam;
	m_wndRj45.m_tcp.Write(&iPFlashPage, 1);
}

/////////////////////////////////////////////////////////////////////////////
// CRj45Wnd

CRj45Wnd::CRj45Wnd()
{
	m_bSavingFile = FALSE;
}

CRj45Wnd::~CRj45Wnd()
{
}

BOOL CRj45Wnd::Create()
{
	// Register a custom WndClass and create a window.
	// This must be done because CRj45Wnd has a custom cursor, and no icon.
	LPCTSTR lpszRj45WndClass = AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW,
													LoadCursor(NULL, IDC_ARROW),
													(HBRUSH)(COLOR_WINDOW+1), NULL);

	return CWnd::CreateEx(0, lpszRj45WndClass, _T(""), WS_POPUPWINDOW,
							0, 0, 0, 0, NULL, 0);
}

void CRj45Wnd::BeginSavingFile(char * p)
{
	m_bSavingFile = TRUE;
	m_iTotalFile = 0;
	m_pFileBuf = p;
}

void CRj45Wnd::EndSavingFile()
{
	m_bSavingFile = FALSE;
}

int CRj45Wnd::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
	if (CWnd::OnCreate(lpCreateStruct) == -1)
		return -1;
	
	// TODO: Add your specialized creation code here
	ULONG uPeerIP = AfxGetApp()->GetProfileInt(_T("Peer"), _T("IPAddress"), 0xc0a80101);
	uPeerIP = MAKELONG(MAKEWORD(HIBYTE(HIWORD(uPeerIP)), LOBYTE(HIWORD(uPeerIP))), MAKEWORD(HIBYTE(LOWORD(uPeerIP)), LOBYTE(LOWORD(uPeerIP))));
	int iPort = AfxGetApp()->GetProfileInt(_T("Peer"), _T("Port"), TCP_DEFAULT_PORT);
	m_tcp.Call(uPeerIP, GetSafeHwnd(), iPort);
	return 0;
}

void CRj45Wnd::OnDestroy() 
{
	CWnd::OnDestroy();
	
	// TODO: Add your message handler code here
//	m_udp.Leave();
	m_tcp.Hangup();
}


BEGIN_MESSAGE_MAP(CRj45Wnd, CWnd)
	//{{AFX_MSG_MAP(CRj45Wnd)
	ON_WM_CREATE()
	ON_WM_DESTROY()
	//}}AFX_MSG_MAP
	ON_MESSAGE(WM_TCP_SOCKET_CLOSE, OnSocketClose)
	ON_MESSAGE(WM_TCP_SOCKET_CONNECT, OnSocketConnect)
	ON_MESSAGE(WM_TCP_SOCKET_DATA, OnSocketData)
END_MESSAGE_MAP()


/////////////////////////////////////////////////////////////////////////////
// CRj45Wnd message handlers
#if _MSC_VER >= 1300
LRESULT CRj45Wnd::OnSocketConnect(WPARAM wParam, LPARAM lParam)
#else
void CRj45Wnd::OnSocketConnect(WPARAM wParam, LPARAM lParam)
#endif
{
	if (m_tcp.GetSocket() == (SOCKET)wParam)
	{
		if (!m_tcp.OnConnect(lParam))
		{
			m_tcp.OnClose();
#if _MSC_VER >= 1300
			return ERROR;
#endif
		}
		SetEvent(CRj45Thread::m_hEventProtocol);
	}
#if _MSC_VER >= 1300
		return 0;
#endif
}

#if _MSC_VER >= 1300
LRESULT CRj45Wnd::OnSocketClose(WPARAM wParam, LPARAM lParam)
#else
void CRj45Wnd::OnSocketClose(WPARAM wParam, LPARAM lParam)
#endif
{
	if (m_tcp.GetSocket() == (SOCKET)wParam)
	{
		m_tcp.OnClose();
	}
#if _MSC_VER >= 1300
	return 0;
#endif
}

#if _MSC_VER >= 1300
LRESULT CRj45Wnd::OnSocketData(WPARAM wParam, LPARAM lParam)
#else
void CRj45Wnd::OnSocketData(WPARAM wParam, LPARAM lParam)
#endif
{
	WSABUF * p = (WSABUF *)lParam;
	BYTE * pBuf = (BYTE *)(p->buf);

	if (m_tcp.GetSocket() == (SOCKET)wParam)
	{
//		OutputDebugBinary(pBuf, p->len);
		if (m_bSavingFile)
		{
			if (p->len == 128)
			{
				memcpy(m_pFileBuf + m_iTotalFile, pBuf, p->len);
				m_iTotalFile += p->len;
				SetEvent(CRj45Thread::m_hEventProtocol);
			}
		}
		else
		{
//			if (pBuf[0] == 0xff && p->len == 1)
			if (pBuf[0] == 0xff)
			{
				SetEvent(CRj45Thread::m_hEventProtocol);
			}
			if (p->len != 1)
			{
				OutputDebugPrintf("tcp length: %d\n", p->len);
				for (int i = 1; i < (int)p->len; i ++)
				{
					OutputDebugPrintf("val[%d]: %d\n", i, pBuf[i]);
				}
			}
		}
	}

	free(p->buf);
	free(p);
#if _MSC_VER >= 1300
	return 0;
#endif
}
