// QMI_NMEADlg.cpp : implementation file
//

#include "stdafx.h"
#include "QMI_NMEA.h"
#include "QMI_NMEADlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

#define TIMER_DeviceSearch				WM_USER + 0x1000
#define WM_USER_NOTIFY_DEVICE_REMOVAL	WM_USER + 0x1001
#define WM_USER_NOTIFY_NMEA		        WM_USER + 0x1002
// global pointer to self
CQMI_NMEADlg* g_This = NULL;
void GOBICALLBACK DeviceRemovalCallback(ULONG nStatus);
void GOBICALLBACK MyNMEACallback(LPCSTR pNMEA);

// CQMI_NMEADlg dialog

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

void CQMI_NMEADlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_STATUS, m_editStatus);
	DDX_Control(pDX, IDC_START, btnStart);
	DDX_Control(pDX, IDC_STOP, btnStop);
	DDX_Control(pDX, IDC_LIST1, lstNMEA);
}

BEGIN_MESSAGE_MAP(CQMI_NMEADlg, CDialog)
#if defined(_DEVICE_RESOLUTION_AWARE) && !defined(WIN32_PLATFORM_WFSP)
	ON_WM_SIZE()
#endif
	//}}AFX_MSG_MAP
	ON_WM_TIMER()
	ON_MESSAGE(WM_USER_NOTIFY_DEVICE_REMOVAL, OnNotifDeviceRemoval)
	ON_MESSAGE(WM_USER_NOTIFY_NMEA, OnWM_NMEA)	 
	ON_BN_CLICKED(IDC_START, &CQMI_NMEADlg::OnBnClickedStart)
	ON_BN_CLICKED(IDC_STOP, &CQMI_NMEADlg::OnBnClickedStop)
	ON_BN_CLICKED(IDC_CLEAR, &CQMI_NMEADlg::OnBnClickedClear)
END_MESSAGE_MAP()


// CQMI_NMEADlg message handlers

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

	// 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
	g_This = this;

	m_DeviceSearchTimer=SetTimer(TIMER_DeviceSearch, 1000, NULL);


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

#if defined(_DEVICE_RESOLUTION_AWARE) && !defined(WIN32_PLATFORM_WFSP)
void CQMI_NMEADlg::OnSize(UINT /*nType*/, int /*cx*/, int /*cy*/)
{
	if (AfxIsDRAEnabled())
	{
		DRA::RelayoutDialog(
			AfxGetResourceHandle(), 
			this->m_hWnd, 
			DRA::GetDisplayMode() != DRA::Portrait ? 
			MAKEINTRESOURCE(IDD_QMI_NMEA_DIALOG_WIDE) : 
			MAKEINTRESOURCE(IDD_QMI_NMEA_DIALOG));
	}
}
#endif


void CQMI_NMEADlg::OnBnClickedStart()
{
	// TODO: Add your control notification handler code here
	SetNMEACallback(MyNMEACallback);
	//StartPDSTrackingSession( 1000);
	SetServiceAutomaticTracking(TRUE);
}

void CQMI_NMEADlg::OnBnClickedStop()
{
	// TODO: Add your control notification handler code here
	SetNMEACallback(MyNMEACallback);
	//StartPDSTrackingSession( 1000);
	SetServiceAutomaticTracking(FALSE);
}

LRESULT CQMI_NMEADlg::OnNotifDeviceRemoval(WPARAM wParam, LPARAM lParam)
{
	UNREFERENCED_PARAMETER(lParam);

	// Shutdown API
	QCWWANDisconnect();
	
	// start timer to search for available device
	SetTimer(TIMER_DeviceSearch, 1000, NULL);
	this->m_editStatus.SetWindowTextW(L"Searching for device...");

	return 0;
}

// Search for available device
BOOL CQMI_NMEADlg::DeviceSearch()
{
	// Attempt to connect to first available device
	if (!QCWWANConnect())
	{
        m_editStatus.SetWindowText(_T("Connected to Device"));
        btnStart.EnableWindow(TRUE);
		btnStop.EnableWindow(TRUE);

        UpdateData(TRUE);

		return TRUE;
	}
	
	return FALSE;
}


void CQMI_NMEADlg::OnTimer(UINT_PTR nIDEvent)
{
	switch (nIDEvent)
	{
		// search for available device
		case TIMER_DeviceSearch:
			KillTimer(nIDEvent);
			if (DeviceSearch())
			{
				// device found

				// Assign GOBI callback handlers
				SwiSetDeviceRemovalCallback(DeviceRemovalCallback);

    	        m_editStatus.SetWindowText(_T("Connected to Device"));


			}
			else
			{
				// Device not found
    	        m_editStatus.SetWindowText(_T("Unable find device"));
                //m_btnSend.EnableWindow(FALSE);
				m_DeviceSearchTimer=SetTimer(TIMER_DeviceSearch, 1000, NULL);
            }
			break;
		default:
			break;
	}

	CDialog::OnTimer(nIDEvent);
}

static void GOBICALLBACK DeviceRemovalCallback(ULONG nStatus)
{
	g_This->PostMessage(WM_USER_NOTIFY_DEVICE_REMOVAL, (WPARAM)nStatus, NULL);
}

static void GOBICALLBACK MyNMEACallback(LPCSTR pNMEA)
{

	//when MyNMEACallback is returned, the memory will be released by the 
	//gobiapi.dll
	//PostMessage will just put the message to a queue, and the message handler of
	//the target window will handle it later.
	//i.e. when the window message handler actually see the pointer, it is already
	//invalid!
	//SendMessage don't return until the handler is completed. so that the handler
	//can use the LPCSTR pNMEA memory safely
	//but if the window message handler is slow, GobiAPI will be stuck waiting for 
	//it to return.
	g_This->SendMessage(WM_USER_NOTIFY_NMEA, (WPARAM)pNMEA, 0);
}


LRESULT CQMI_NMEADlg::OnWM_NMEA(WPARAM wParam, LPARAM lParam)
{
	LPCSTR NMEAMsg=(LPCSTR)wParam;
	DWORD sizerequired=MultiByteToWideChar(CP_ACP, 0, NMEAMsg, -1, NULL, 0);
	WCHAR* wNMEAMsg=(WCHAR*)malloc(sizerequired*2);
	if (wNMEAMsg) 
		MultiByteToWideChar(CP_ACP, 0, NMEAMsg, -1, wNMEAMsg, sizerequired);

	this->lstNMEA.InsertString(0, wNMEAMsg);
	if (this->lstNMEA.GetCount()>100)
		lstNMEA.DeleteString(this->lstNMEA.GetCount()-1);
	if (wNMEAMsg) free(wNMEAMsg);
	return 0;
}
void CQMI_NMEADlg::OnBnClickedClear()
{
	lstNMEA.ResetContent();
	// TODO: Add your control notification handler code here
}


/////////////////////////////////////////////////////////////////////////////
//
//	Function	:	OnCancel
//
//	Description	:	Handler for IDCANCEL
//
//	Arguments	:	None
//
//	Returns		:	None
//
//	Comments	:	
//
/////////////////////////////////////////////////////////////////////////////
void CQMI_NMEADlg::OnCancel() 
{
	// clear callback handlers
	SwiSetDeviceRemovalCallback(NULL);
    SetNMEACallback(NULL);

	// disconnect from device
	QCWWANDisconnect();
    g_This = NULL;
	
	CDialog::OnCancel();
}

void CQMI_NMEADlg::OnOK() 
{
	OnCancel();
}
