// NetUsersDiag.cpp : implementation file
//

#ifdef DENETWINSERVER
 #include "..\deNetWinServer\stdafx.h"
 #include "..\deNetWinServer\deNetWinServer.h"
#else
 #include "..\deNetWinClient\stdafx.h"
 #include "..\deNetWinClient\deNetWinClient.h"
#endif
#include "NetUsersDiag.h"
#include "..\deNet\deConnection.hpp"

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

/////////////////////////////////////////////////////////////////////////////
// CNetUsersDiag

CNetUsersDiag * CNetUsersDiag::m_Singleton = NULL;

IMPLEMENT_DYNCREATE(CNetUsersDiag, CFormView)

CNetUsersDiag::CNetUsersDiag()
	: CFormView(CNetUsersDiag::IDD)
{
	m_Singleton = this;

	//{{AFX_DATA_INIT(CNetUsersDiag)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
}

CNetUsersDiag::~CNetUsersDiag()
{
	m_Singleton = NULL;
}

void CNetUsersDiag::DoDataExchange(CDataExchange* pDX)
{
	CFormView::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CNetUsersDiag)
	DDX_Control(pDX, IDC_LST_NETUSERS, m_lstNetUsers);
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CNetUsersDiag, CFormView)
	//{{AFX_MSG_MAP(CNetUsersDiag)
	ON_WM_SIZE()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CNetUsersDiag diagnostics

#ifdef _DEBUG
void CNetUsersDiag::AssertValid() const
{
	CFormView::AssertValid();
}

void CNetUsersDiag::Dump(CDumpContext& dc) const
{
	CFormView::Dump(dc);
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CNetUsersDiag message handlers

void CNetUsersDiag::OnSize(UINT nType, int cx, int cy) 
{
	CFormView::OnSize(nType, cx, cy);
	
	if( m_lstNetUsers.m_hWnd )
	{
		// resize controls
		m_lstNetUsers.MoveWindow( 0, 0, cx, cy, TRUE );
		m_lstNetUsers.UpdateWindow();
	}
}

void CNetUsersDiag::OnInitialUpdate() 
{
	CFormView::OnInitialUpdate();

	int			iRet = 0;
	LVCOLUMN	col;

	// setup control
	m_lstNetUsers.SetExtendedStyle(LVS_EX_FULLROWSELECT /*| LVS_EX_TRACKSELECT */ );
	m_lstNetUsers.EnableToolTips( FALSE );
	
	// clear control
	m_lstNetUsers.DeleteAllItems();
	m_lstNetUsers.DeleteColumn( 0 );
	m_lstNetUsers.DeleteColumn( 0 );
	m_lstNetUsers.DeleteColumn( 0 );
	m_lstNetUsers.DeleteColumn( 0 );
	m_lstNetUsers.DeleteColumn( 0 );

	// clear it
	memset( &col, 0, sizeof(LVCOLUMN) );
	col.mask		= LVCF_TEXT | LVCF_WIDTH ;
	col.cx			= 100;
	
	// setup column
	col.pszText		= "Net ID";
	col.iSubItem	= 0;

	// add column
	iRet = m_lstNetUsers.InsertColumn( 0, &col );

	// setup column
	col.pszText		= "IP Address";
	col.iSubItem	= 1;

	// add column
	iRet = m_lstNetUsers.InsertColumn( 1, &col );

	// setup column
	col.pszText		= "Connection Type";
	col.iSubItem	= 2;

	// add column
	iRet = m_lstNetUsers.InsertColumn( 2, &col );

	// setup column
	col.pszText		= "Average Lag";
	col.iSubItem	= 3;

	// add column
	iRet = m_lstNetUsers.InsertColumn( 3, &col );

	// setup column
	col.pszText		= "Session Time (Appx)";
	col.iSubItem	= 4;

	// add column
	iRet = m_lstNetUsers.InsertColumn( 4, &col );
}

void CNetUsersDiag::UpdateConnectionInfo( deConnection * pConn )
{
	ASSERT( pConn );

	LVFINDINFO	info;
	int			iRow		= -1;
	CString		strNetID	= "";
	CString		strType		= "";

	strNetID.Format( "%u", pConn->GetConnDesc()->m_hRemoteUser );
	info.flags	= LVFI_STRING;
	info.psz	= strNetID.GetBuffer( strNetID.GetLength() );

	iRow = m_lstNetUsers.FindItem( &info );

	if( iRow >= 0 )
	{
		m_lstNetUsers.SetRedraw( FALSE );

		// set ip address
		m_lstNetUsers.SetItemText( iRow, 1, pConn->GetConnDesc()->m_RemoteAddress.GetAddressIPStr() );

		switch( pConn->GetType() )
		{
		case deConnection::TYPE_TCP:
			strType = "TCP";
			break;
		case deConnection::TYPE_UDP:
			strType = "UDP";
			break;
		default:
			strType = "Unknown";
			break;
		}

		// set connection type
		m_lstNetUsers.SetItemText( iRow, 2, strType.GetBuffer( strType.GetLength() ) );

		// set avg lag
		strType.Format( "%I64f", pConn->GetAvgLag()/(double)1000000.0 );
		m_lstNetUsers.SetItemText( iRow, 3, strType.GetBuffer( strType.GetLength() ) );

		// set session time
		strType.Format( "%I64f", pConn->GetOwner()->GetApproxSessionTime()/(double)1000000.0 );
		m_lstNetUsers.SetItemText( iRow, 4, strType.GetBuffer( strType.GetLength() ) );

		m_lstNetUsers.SetRedraw( TRUE );
		m_lstNetUsers.UpdateWindow();
	}
}

bool CNetUsersDiag::RemoveConnection( deConnection * pConn )
{
	LVFINDINFO	info;
	int			iRow		= -1;
	CString		strNetID	= "";
	CString		strType		= "";

	strNetID.Format( "%u", pConn->GetConnDesc()->m_hRemoteUser );
	info.flags	= LVFI_STRING;
	info.psz	= strNetID.GetBuffer( strNetID.GetLength() );

	iRow = m_lstNetUsers.FindItem( &info );

	if( iRow >= 0 )
	{
		m_lstNetUsers.SetRedraw( FALSE );
		m_lstNetUsers.DeleteItem( iRow );
		m_lstNetUsers.SetRedraw( TRUE );
		m_lstNetUsers.UpdateWindow();
	}

	return iRow >= 0;
}

bool CNetUsersDiag::AddConnection( deConnection * pConn )
{
	ASSERT( pConn );

	// setup item struct
	int		iRet =  0;
	int		iImg = -1;
	LVITEM	item;
	memset( &item, 0,sizeof(LVITEM) );

	CString strText;

	if( iImg >= 0 )
		item.mask	= LVIF_TEXT | LVIF_IMAGE | LVIF_STATE;
	else
		item.mask	= LVIF_TEXT | LVIF_STATE;

	item.iImage		= iImg;
	item.iItem		= m_lstNetUsers.GetItemCount();
	item.state		= LVIS_SELECTED | LVIS_FOCUSED;
	item.stateMask	= (UINT)-1;
		
	// user id
	strText.Format( "%u", pConn->GetConnDesc()->m_hRemoteUser );
	item.pszText	= strText.GetBuffer( strText.GetLength() );
	item.iSubItem	= 0;
	iRet = m_lstNetUsers.InsertItem( &item );

	if( iRet >= 0 )
	{
		UpdateConnectionInfo( pConn );
	}

	if( iRet < 0 )
		return false;
	else
		return true;
}
