#include "pch.h"
#include "Lan.h"
#include <locale.h>
#include <mmsystem.h>

// Constructor
CLan::CLan()
	: m_Socket()
	, m_TransferBuffer()
	, m_ReceiveData(_T(""))
{
}

// Destructor
CLan::~CLan()
{
}

// (1)Connect
BOOL CLan::OpenInterface(CString HostAddress, UINT HostPort)
{
#ifdef _UNICODE
	size_t Length;
#endif
	char IpAddress[64];
	CString ErrorMessage;
	int Result;

#ifdef _UNICODE
	wcstombs_s(&Length, IpAddress, sizeof(IpAddress), HostAddress, _TRUNCATE);			// Converts a wide characters to multibyte characters
#else
	_tcscpy_s(IpAddress, sizeof(IpAddress), HostAddress);
#endif
	Result = m_Socket.Connect(IpAddress, HostPort);										// Open socket
	if (Result != 0) {
		ErrorMessage = GetLastErrorMessage(Result);
		MessageBox(NULL, ErrorMessage, AfxGetAppName(), MB_ICONERROR | MB_OK);
		return FALSE;
	}

	return TRUE;
}

// (2)Disconnect
void CLan::CloseInterface()
{
	CString ErrorMessage;
	int Result;

	Result = m_Socket.Disconnect();														// Close socket
	if (Result != 0) {
		ErrorMessage = GetLastErrorMessage(Result);
		MessageBox(NULL, ErrorMessage, AfxGetAppName(), MB_ICONERROR | MB_OK);
	}
}

// (3)Send commands
BOOL CLan::SendMsg(CString SendData)
{
#ifdef _UNICODE
	size_t Length;
#endif
	CString ErrorMessage;
	int Result;

	SendData = SendData + _T("\r\n");													// Add a terminator, CR+LR, to transmitted command
#ifdef _UNICODE
	wcstombs_s(&Length, m_TransferBuffer, sizeof(m_TransferBuffer), SendData, _TRUNCATE);	// Converts a wide characters to multibyte characters
#else
	_tcscpy_s(m_TransferBuffer, sizeof(m_TransferBuffer), SendData);
#endif
	Result = m_Socket.Send(m_TransferBuffer);											// Write data in the transmit buffer
	if (Result != 0) {
		ErrorMessage = GetLastErrorMessage(Result);
		MessageBox(NULL, ErrorMessage, AfxGetAppName(), MB_ICONERROR | MB_OK);
		return FALSE;
	}

	return TRUE;
}

// (4)Receive
BOOL CLan::ReceiveMsg(DWORD Timeout)
{
	DWORD StartTime;
	CString Buffer;
	BOOL Status = FALSE;
	CString ErrorMessage;
	int Result;

	m_ReceiveData = _T("");																// Clear received data
	StartTime = timeGetTime();
	// Continue the loop until LF is received
	for (;;) {
		Result = m_Socket.Receive(Buffer, 1000);										// Read data from the receive buffer
		if (Result != 0) {
			m_ReceiveData = _T("Error");
			ErrorMessage = GetLastErrorMessage(Result);
			MessageBox(NULL, ErrorMessage, AfxGetAppName(), MB_ICONERROR | MB_OK);
			Status = FALSE;
			break;
		}
		if (Buffer.GetLength() > 1) {
			Buffer.Replace(_T("\r"), _T(""));											// Delete CR in received data
			int Index = Buffer.Find(_T("\n"));
			if (Index >= 0) {															// End the loop when LF is received
				m_ReceiveData = m_ReceiveData + Buffer.Mid(0, Index);					// Extract data without LF and the following from the original received data
				Status = TRUE;;
				break;
			}
			else {
				m_ReceiveData = m_ReceiveData + Buffer;									// Save the data
			}
		}
		// Timeout processing
		if (timeGetTime() > StartTime + Timeout) {
			m_ReceiveData = _T("Timeout");
			Status = FALSE;
			break;
		}
	}

	return Status;
}

// (5)Transmit and receive commands
BOOL CLan::SendQueryMsg(CString SendData, DWORD Timeout)
{
	BOOL Result;

	Result = SendMsg(SendData);															// Transmit commands
	if (Result == TRUE) {
		if (SendData.Find(_T("?")) != -1) {
			Result = ReceiveMsg(Timeout);												// Receive response when command transmission is succeeded
		}
	}

	return Result;
}

// Get error message
CString CLan::GetLastErrorMessage(DWORD MessageId)
{
	PVOID pBuffer = NULL;
	CString ErrorMessage;

	if (FormatMessage(
		FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_MAX_WIDTH_MASK,
		NULL, MessageId, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), reinterpret_cast<PTSTR>(&pBuffer), 0, NULL) == 0 || pBuffer == NULL) {
		return ErrorMessage;
	}
	ErrorMessage = static_cast<PTSTR>(pBuffer);
	LocalFree(pBuffer);

	return ErrorMessage;
}
