// WiFiDirectClientDlg.cpp : implementation file
//

#include "stdafx.h"
#include "WiFiDirectClient.h"
#include "WiFiDirectClientDlg.h"
#include "PinDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// CWiFiDirectClientDlg dialog




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

void CWiFiDirectClientDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_LIST_DEVICES, lvDevices);
	DDX_Control(pDX, IDC_LIST_LOG, lbLog);
	DDX_Control(pDX, IDC_COMBO2, cbPairingProcedure);
	DDX_Control(pDX, IDC_EDIT1, edGroupOwnerIntent);
	DDX_Control(pDX, IDC_CHECK2, cbDisplayPin);
	DDX_Control(pDX, IDC_CHECK3, cbProvidePin);
	DDX_Control(pDX, IDC_CHECK4, cbPushButton);
}

BEGIN_MESSAGE_MAP(CWiFiDirectClientDlg, CDialog)
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	//}}AFX_MSG_MAP
	ON_BN_CLICKED(IDC_BUTTON_DISCOVER, &CWiFiDirectClientDlg::OnBnClickedButtonDiscover)
	ON_BN_CLICKED(IDC_BUTTON_TERMINATE, &CWiFiDirectClientDlg::OnBnClickedButtonTerminate)
	ON_WM_DESTROY()
	ON_BN_CLICKED(IDC_BUTTON_CLEAR, &CWiFiDirectClientDlg::OnBnClickedButtonClear)
	ON_BN_CLICKED(IDC_BUTTON_DISCONNECT, &CWiFiDirectClientDlg::OnBnClickedButtonDisconnect)
	ON_BN_CLICKED(IDC_BUTTON_CONNECT, &CWiFiDirectClientDlg::OnBnClickedButtonConnect)
	ON_BN_CLICKED(IDC_BUTTON_IS_PAIRED, &CWiFiDirectClientDlg::OnBnClickedButtonIsPaired)
	ON_BN_CLICKED(IDC_BUTTON_UNPAIR, &CWiFiDirectClientDlg::OnBnClickedButtonUnpair)
	ON_BN_CLICKED(IDC_BUTTON_GET_NAME, &CWiFiDirectClientDlg::OnBnClickedButtonGetName)
	ON_BN_CLICKED(IDC_BUTTON_ENUM_PAIRED, &CWiFiDirectClientDlg::OnBnClickedButtonEnumPaired)
END_MESSAGE_MAP()


// CWiFiDirectClientDlg message handlers

BOOL CWiFiDirectClientDlg::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

	lvDevices.InsertColumn(0, _T("Name"), 0, 150);
	lvDevices.InsertColumn(1, _T("ID"), 0, 200);
	lvDevices.SetExtendedStyle(lvDevices.GetExtendedStyle() | LVS_EX_FULLROWSELECT);

	cbPairingProcedure.AddString(_T("ppInvitation"));
	cbPairingProcedure.AddString(_T("ppGroupOwnerNegotiation"));
	cbPairingProcedure.SetCurSel(0);

	edGroupOwnerIntent.SetWindowText(_T("14"));

	cbPushButton.SetCheck(TRUE);

	__hook(&CwclWiFiDirectDeviceWatcher::OnDeviceFound, &Watcher, &CWiFiDirectClientDlg::wclWiFiDirectDeviceWatcherDeviceFound);
	__hook(&CwclWiFiDirectDeviceWatcher::OnDiscoveringCompleted, &Watcher, &CWiFiDirectClientDlg::wclWiFiDirectDeviceWatcherDiscoveringCompleted);
	__hook(&CwclWiFiDirectDeviceWatcher::OnDiscoveringStarted, &Watcher, &CWiFiDirectClientDlg::wclWiFiDirectDeviceWatcherDiscoveringStarted);

	__hook(&CwclWiFiDirectClient::OnDeviceConnected, &Client, &CWiFiDirectClientDlg::wclWiFiDirectClientDeviceConnected);
	__hook(&CwclWiFiDirectClient::OnPairCompleted, &Client, &CWiFiDirectClientDlg::wclWiFiDirectClientPairCompleted);
	__hook(&CwclWiFiDirectClient::OnPairConfirm, &Client, &CWiFiDirectClientDlg::wclWiFiDirectClientPairConfirm);
	__hook(&CwclWiFiDirectClient::OnPairDisplayPin, &Client, &CWiFiDirectClientDlg::wclWiFiDirectClientPairDisplayPin);
	__hook(&CwclWiFiDirectClient::OnPairProvidePin, &Client, &CWiFiDirectClientDlg::wclWiFiDirectClientPairProvidePin);
	__hook(&CwclWiFiDirectClient::OnDeviceDisconnected, &Client, &CWiFiDirectClientDlg::wclWiFiDirectClientDeviceDisconnected);
	__hook(&CwclWiFiDirectClient::OnPairGetParams, &Client, &CWiFiDirectClientDlg::wclWiFiDirectClientPairGetParams);

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

// 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 CWiFiDirectClientDlg::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 CWiFiDirectClientDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}

void CWiFiDirectClientDlg::wclWiFiDirectDeviceWatcherDeviceFound(void* Sender, 
	const tstring& Id, const tstring& Name)
{
	UNREFERENCED_PARAMETER(Sender);

	int n = lvDevices.GetItemCount();
	lvDevices.InsertItem(n, Name.c_str());
	lvDevices.SetItemText(n, 1, Id.c_str());
	
	lbLog.AddString(_T("Device found"));
}

void CWiFiDirectClientDlg::wclWiFiDirectDeviceWatcherDiscoveringCompleted(void* Sender,
	const int Error)
{
	UNREFERENCED_PARAMETER(Sender);

	CString s;
	s.Format(_T("Discovering completed with result: 0x%.8X"), Error);
	lbLog.AddString(s);
}

void CWiFiDirectClientDlg::wclWiFiDirectDeviceWatcherDiscoveringStarted(void* Sender)
{
	UNREFERENCED_PARAMETER(Sender);

	lvDevices.DeleteAllItems();
	lbLog.AddString(_T("Discovering started"));
}

void CWiFiDirectClientDlg::OnBnClickedButtonDiscover()
{
	int Res = Watcher.Discover();
	if (Res != WCL_E_SUCCESS)
	{
		CString s;
		s.Format(_T("Discover error: 0x%.8X"), Res);
		AfxMessageBox(s);
	}
}

void CWiFiDirectClientDlg::OnBnClickedButtonTerminate()
{
	int Res = Watcher.Terminate();
	if (Res != WCL_E_SUCCESS)
	{
		CString s;
		s.Format(_T("Terminate error: 0x%.8X"), Res);
		AfxMessageBox(s);
	}
}

void CWiFiDirectClientDlg::OnDestroy()
{
	CDialog::OnDestroy();

	Client.Disconnect();
	Watcher.Terminate();

	__unhook(&Watcher);
	__unhook(&Client);
}

void CWiFiDirectClientDlg::OnBnClickedButtonClear()
{
	lbLog.ResetContent();
}

void CWiFiDirectClientDlg::OnBnClickedButtonDisconnect()
{
	int Res = Client.Disconnect();
	if (Res != WCL_E_SUCCESS)
	{
		CString s;
		s.Format(_T("Disconnect error: 0x%.8X"), Res);
		AfxMessageBox(s);
	}
}

void CWiFiDirectClientDlg::OnBnClickedButtonConnect()
{
	POSITION Pos = lvDevices.GetFirstSelectedItemPosition();
	if (Pos == NULL)
		AfxMessageBox(_T("Select device"));
	else
	{
		CString Id = lvDevices.GetItemText(lvDevices.GetNextSelectedItem(Pos), 1);
		int Res = Client.Connect(tstring(Id));
		if (Res != WCL_E_SUCCESS)
		{
			CString s;
			s.Format(_T("Connect Error: 0x%.8X"), Res);
			AfxMessageBox(s);
		}
	}
}

void CWiFiDirectClientDlg::wclWiFiDirectClientDeviceConnected(void* Sender,
	CwclWiFiDirectDevice* const Device, const int Error)
{
	UNREFERENCED_PARAMETER(Sender);
	UNREFERENCED_PARAMETER(Device);

	CString s;
	s.Format(_T("Connected with result: 0x%.8X"), Error);
	lbLog.AddString(s);
	if (Error == WCL_E_SUCCESS)
	{
		lbLog.AddString(_T("  Local IP: ") + CString(Client.LocalAddress.c_str()));
		lbLog.AddString(_T("  Remote IP: ") + CString(Client.RemoteAddress.c_str()));
	}
}

void CWiFiDirectClientDlg::wclWiFiDirectClientPairCompleted(void* Sender,
	CwclWiFiDirectDevice* const Device, const int Result)
{
	UNREFERENCED_PARAMETER(Sender);
	UNREFERENCED_PARAMETER(Device);

	CString s;
	s.Format(_T("Pairing completed with result: 0x%.8X"), Result);
	lbLog.AddString(s);
}

void CWiFiDirectClientDlg::wclWiFiDirectClientPairConfirm(void* Sender,
	CwclWiFiDirectDevice* const Device, bool& Confirm)
{
	UNREFERENCED_PARAMETER(Sender);
	UNREFERENCED_PARAMETER(Device);

	Confirm = (AfxMessageBox(_T("Confirm pairing"), MB_YESNO | MB_APPLMODAL | MB_ICONQUESTION) == IDYES);
}

void CWiFiDirectClientDlg::wclWiFiDirectClientPairDisplayPin(void* Sender,
	CwclWiFiDirectDevice* const Device, const tstring& Pin)
{
	UNREFERENCED_PARAMETER(Sender);
	UNREFERENCED_PARAMETER(Device);

	tstring s = _T("Use ") + Pin + _T(" PIN to pair");
	AfxMessageBox(s.c_str());
}

void CWiFiDirectClientDlg::wclWiFiDirectClientPairGetParams(void* Sender,
	CwclWiFiDirectDevice* Device, short& GroupOwnerIntent,
	wclWiFiDirectConfigurationMethods& ConfigurationMethods,
	wclWiFiDirectPairingProcedure& PairingProcedure)
{
	UNREFERENCED_PARAMETER(Sender);

	lbLog.AddString(Device->Name.c_str() + CString(_T(" quering pairing params")));
	
	if (cbPairingProcedure.GetCurSel() == 0)
		PairingProcedure = ppInvitation;
	else
		PairingProcedure = ppGroupOwnerNegotiation;

	CString s;
	edGroupOwnerIntent.GetWindowText(s);
	GroupOwnerIntent = LOWORD(_ttoi(s));
	
	ConfigurationMethods.clear();
	if (cbDisplayPin.GetCheck())
		ConfigurationMethods.insert(cmDisplayPin);
	if (cbProvidePin.GetCheck())
		ConfigurationMethods.insert(cmProvidePin);
	if (cbPushButton.GetCheck())
		ConfigurationMethods.insert(cmPushButton);
}

void CWiFiDirectClientDlg::wclWiFiDirectClientPairProvidePin(void* Sender,
	CwclWiFiDirectDevice* const Device, tstring& Pin)
{
	UNREFERENCED_PARAMETER(Sender);
	UNREFERENCED_PARAMETER(Device);

	Pin = _T("");
	CPinDlg Dlg;
	if (Dlg.DoModal() == IDOK)
	{
		CString s;
		Dlg.edPin.GetWindowText(s);
		Pin = s;
	}
}

void CWiFiDirectClientDlg::wclWiFiDirectClientDeviceDisconnected(void* Sender,
	CwclWiFiDirectDevice* const Device, const int Reason)
{
	UNREFERENCED_PARAMETER(Sender);
	UNREFERENCED_PARAMETER(Device);

	CString s;
	s.Format(_T("Disconnected. Reason: 0x%.8X"), Reason);
	lbLog.AddString(s);
}

void CWiFiDirectClientDlg::OnBnClickedButtonIsPaired()
{
	POSITION Pos = lvDevices.GetFirstSelectedItemPosition();
	if (Pos == NULL)
		AfxMessageBox(_T("Select device"));
	else
	{
		CString Id = lvDevices.GetItemText(lvDevices.GetNextSelectedItem(Pos), 1);
		bool IsPaired;
		int Res = Watcher.IsPaired(tstring(Id), IsPaired);
		if (Res != WCL_E_SUCCESS)
		{
			CString s;
			s.Format(_T("Get paired error: 0x%.8X"), Res);
			AfxMessageBox(s);
		}
		else
		{
			if (IsPaired)
				AfxMessageBox(_T("Device is paired"));
			else
				AfxMessageBox(_T("Device is NOT paired"));
		}
	}
}

void CWiFiDirectClientDlg::OnBnClickedButtonUnpair()
{
	POSITION Pos = lvDevices.GetFirstSelectedItemPosition();
	if (Pos == NULL)
		AfxMessageBox(_T("Select device"));
	else
	{
		CString Id = lvDevices.GetItemText(lvDevices.GetNextSelectedItem(Pos), 1);
		int Res = Watcher.Unpair(tstring(Id));
		if (Res != WCL_E_SUCCESS)
		{
			CString s;
			s.Format(_T("Unpair error: 0x%.8X"), Res);
			AfxMessageBox(s);
		}
		else
			AfxMessageBox(_T("Unpaired"));
	}
}

void CWiFiDirectClientDlg::OnBnClickedButtonGetName()
{
	POSITION Pos = lvDevices.GetFirstSelectedItemPosition();
	if (Pos == NULL)
		AfxMessageBox(_T("Select device"));
	else
	{
		CString Id = lvDevices.GetItemText(lvDevices.GetNextSelectedItem(Pos), 1);
		tstring Name;
		int Res = Watcher.GetName(tstring(Id), Name);
		if (Res != WCL_E_SUCCESS)
		{
			CString s;
			s.Format(_T("Get name error: 0x%.8X"), Res);
			AfxMessageBox(s);
		}
		else
		{
			CString s(Name.c_str());
			AfxMessageBox(_T("Device name: ") + s);
		}
	}
}

void CWiFiDirectClientDlg::OnBnClickedButtonEnumPaired()
{
	WCL_WFD_DEVICES Paired;
	int Res = Watcher.EnumPairedDevices(&Paired);
	if (Res != WCL_E_SUCCESS)
	{
		CString s;
		s.Format(_T("Enum paired error: 0x%.8X"), Res);
		AfxMessageBox(s);
	}
	else
	{
		lvDevices.DeleteAllItems();

		if (Paired.size() > 0)
		{
			for (WCL_WFD_DEVICES::iterator i = Paired.begin(); i != Paired.end(); i++)
			{
				tstring Name;
				Res = Watcher.GetName((*i), Name);
				if (Res != WCL_E_SUCCESS)
				{
					CString s;
					s.Format(_T("Error: 0x%.8X"), Res);
					Name = s;
				}

				int n = lvDevices.GetItemCount();
				lvDevices.InsertItem(n, Name.c_str());
				lvDevices.SetItemText(n, 1, (*i).c_str());
			}
		}
	}
}
