/*
*******************************************************************************
* Copyright (c) 1996-2000 Digi International Inc., All Rights Reserved        *
*                                                                             *
* This  software  contains  proprietary  and  confidential   information   of *
* Digi International  Inc.   By  accepting  transfer  of this copy, Recipient *
* agrees to retain this software in  confidence,  to  prevent  disclosure  to *
* others,  and  to make no  use of this software other than that for which it *
* was delivered.  This is an unpublished copyright work  Digi   International *
* Inc.    Except   as   permitted   by  federal  law,  17 USC 117, copying is *
* strictly prohibited.                                                        *
*                                                                             *
* Digi  International  Inc.  CONFIDENTIAL  -   (Digi    International    Inc. *
* Confidential  when   combined   with   the   aggregated  modules  for  this *
* product) OBJECT CODE ONLY SOURCE MATERIALS                                  *
*                                                                             *
* (C) COPYRIGHT Digi International Inc. 1996-97                               *
*                                                                             *
* All Rights Reserved                                                         *
*                                                                             *
* US   Government   Users   Restricted   Rights   -   Use,   duplication   or *
* disclosure  restricted by GSA ADP Schedule Contract with Digi International *
* Inc.                                                                        *
*                                                                             *
*******************************************************************************

// StatDoc.cpp : implementation file
//

*/

#include "stdafx.h"
#include "Diagnostic.h"
#include "StatDoc.h"
#include "StatView.h"

#include "MainFrm.h"
#include "DataSource.h"

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

/////////////////////////////////////////////////////////////////////////////
// CStatDoc

IMPLEMENT_DYNCREATE(CStatDoc, CDocument)

CStatDoc::CStatDoc()
{
}

BOOL CStatDoc::OnNewDocument()
{
	if (!CDocument::OnNewDocument())
		return FALSE;

	m_ClearWanStats = CWAN();

	m_LastStatus = m_pDataSource->GetStatus(m_pDataSource->GetDefaultFirmwareDevice());
	m_ByteRate = m_pDataSource->GetByteRate();

	m_LU[0] = m_LU[1] = 0;
	m_FPS[0] = m_FPS[1] = 0;
	m_BPS[0] = m_BPS[1] = 0;
	m_AverageFPS[0] = m_AverageFPS[1] = 0;
	m_AverageBPS[0] = m_AverageBPS[1] = 0;
	m_Overflow[0] = m_Overflow[1] = 0;

	_timeb zero = { 0 };
	m_LastTime = m_StartTime = zero;
	m_LastInterval = 0;

	return TRUE;
}

CStatDoc::~CStatDoc()
{
}


BEGIN_MESSAGE_MAP(CStatDoc, CDocument)
	//{{AFX_MSG_MAP(CStatDoc)
	ON_COMMAND(ID_EDIT_CLEARSTATISTICS, OnEditClearstatistics)
	ON_UPDATE_COMMAND_UI(ID_FILE_SAVE, OnUpdateFileSave)
	ON_CBN_SELCHANGE(IDW_DataSource, OnSelchangeDataSource)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CStatDoc diagnostics

#ifdef _DEBUG
void CStatDoc::AssertValid() const
{
	CDocument::AssertValid();
}

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

/////////////////////////////////////////////////////////////////////////////
// CStatDoc serialization

void CStatDoc::Serialize(CArchive& ar)
{
	if (ar.IsStoring())
	{
		// TODO: add storing code here
	}
	else
	{
		// TODO: add loading code here
	}
}

/////////////////////////////////////////////////////////////////////////////
// CStatDoc commands

void CStatDoc::OnSelchangeDataSource()
{
	CComboBox& box = static_cast<CMainFrame *>(AfxGetMainWnd())->m_DataSourceBox;

	int nIndex = box.GetCurSel();
	ASSERT(nIndex > CB_ERR);

	CDataSourceControl *pControl = (CDataSourceControl *)box.GetItemDataPtr(nIndex);
	ASSERT(pControl != NULL);	

	CDataSource *pChangetoDataSource = pControl->GetDataSource();
	ASSERT(pChangetoDataSource != NULL);

// user set combo box to datasource this window is already using
	if (pChangetoDataSource == m_pDataSource)
		return;

// user set combo box to datasource were stats are unavailable
	if (pControl->GetState() == dsiNone)
	{
		for (short iItem = 0; iItem < box.GetCount(); iItem++)
		{
			CDataSourceControl *pControl = (CDataSourceControl *)box.GetItemDataPtr(iItem);
			ASSERT(pControl != NULL);

			if (pControl->GetDataSource() == m_pDataSource)
				break;
		}

		ASSERT(iItem < box.GetCount());
		box.SetCurSel(iItem);

// set it back to datasource this window is using
		return;
	}

// create new stats windows
	AfxGetApp()->OnCmdMsg(ID_CAPTURE_DISPLAYSTATISTICS, 0, NULL, NULL);
// destroy this one
	POSITION Pos = GetFirstViewPosition();
	CView *pView = GetNextView(Pos);
	pView->GetParentFrame()->DestroyWindow();
}

void CStatDoc::OnIdle()
{
	eDataSourceStatus now = GetDataSource()->GetStatus(GetDataSource()->GetDefaultFirmwareDevice());
	
	if (now != m_LastStatus)
	{
		POSITION pos = GetFirstViewPosition();

		while (pos)
			GetNextView(pos)->OnInitialUpdate();

		m_ByteRate = m_pDataSource->GetByteRate();
	}

	m_LastStatus = now;

	if (m_LastStatus == dssRunning)
	{
		GetProtocolStats();
		UpdateAllViews(NULL, uavUpdateStats);
	}
}

void CStatDoc::OnEditClearstatistics() 
{
	// TODO: Add your command handler code here
	m_pDataSource->UpdateDataSourceStats();
	ClearProtocolStats();
	UpdateAllViews(NULL, uavUpdateStats);
}

void CStatDoc::ClearProtocolStats()
{
	m_LU[0] = m_LU[1] = 0;
	m_FPS[0] = m_FPS[1] = 0;
	m_BPS[0] = m_BPS[1] = 0;
	m_AverageFPS[0] = m_AverageFPS[1] = 0;
	m_AverageBPS[0] = m_AverageBPS[1] = 0;
	m_Overflow[0] = m_Overflow[1] = 0;

	const CWAN& WanStats = *(CWAN *)GetStatType(typeid(CWAN));

	m_LastFPS[0] = m_StartFPS[0] = WanStats->hc_txgood;
	m_LastFPS[1] = m_StartFPS[1] = WanStats->hc_rxgood;
	m_LastBPS[0] = m_StartBPS[0] = WanStats->hc_txgdbytes;
	m_LastBPS[1] = m_StartBPS[1] = WanStats->hc_rxgdbytes;

	m_ClearWanStats = WanStats;

	m_LastTime = m_pDataSource->GetUpdateTime();
	m_StartTime = m_LastTime;
	m_LastInterval = 0;
}


template<class UserIOCTL>
void HandleOverflow(UserIOCTL& Stats, UserIOCTL& ClearStats, const DWORD MaxValue = _UI32_MAX)
{
	for (short i = 0; i < Stats.GetStatCount(); i++)
		if (Stats[i] >= ClearStats[i])
			Stats[i] -= ClearStats[i];
		else
			Stats[i] += (USHORT)(MaxValue - ClearStats[i]);
}

template<class TYPE>
void HandleOverflowEx(TYPE& Stat, TYPE& ClearStat, const DWORD MaxValue = _UI32_MAX)
{
	if (Stat >= ClearStat)
		Stat -= ClearStat;
	else
		Stat += ((TYPE)MaxValue - ClearStat);
}


void CStatDoc::GetProtocolStats()
{
	m_WanStats = *(CWAN *)GetStatType(typeid(CWAN));
	m_WanLineStatus = *(CWANLINESTATUS *)GetStatType(typeid(CWANLINESTATUS));

	if (m_StartTime.time == 0)
	{
		m_LastFPS[0] = m_StartFPS[0] = m_WanStats->hc_txgood;
		m_LastFPS[1] = m_StartFPS[1] = m_WanStats->hc_rxgood;
		m_LastBPS[0] = m_StartBPS[0] = m_WanStats->hc_txgdbytes;
		m_LastBPS[1] = m_StartBPS[1] = m_WanStats->hc_rxgdbytes;

		m_LastTime = m_pDataSource->GetUpdateTime();
		m_StartTime = m_LastTime;
	
		return;
	}

	_timeb now = m_pDataSource->GetUpdateTime();

	DWORD frames[2] = { m_WanStats->hc_txgood, m_WanStats->hc_rxgood };
	DWORD bytes[2] = { m_WanStats->hc_txgdbytes, m_WanStats->hc_rxgdbytes };
//	TRACE( "txgdbytes %d, rxgdbytes %d\n", bytes[0], bytes[1] );

	// check to see if a number overflowed 32bits
	for (short i = 0; i < 2; i++)
	{
		if (m_StartFPS[i] > frames[i] || m_LastFPS[i] > frames[i])
		{
			ClearProtocolStats();
			return;
		}
	}

	double AveInterval = (now.time - m_StartTime.time) + (now.millitm - m_StartTime.millitm) / 1000.0;

	if (AveInterval - m_LastInterval >= 1.0)
	{
		for (short i = 0; i < 2; i++)
		{
			if (frames[i] >= m_StartFPS[i])
				m_AverageFPS[i] = round((frames[i] - m_StartFPS[i]) / AveInterval);
			else
				m_StartFPS[i] = frames[i];
			
			if (bytes[i] >= m_StartBPS[i])
				m_AverageBPS[i] = round((bytes[i] - m_StartBPS[i]) / AveInterval);
			else
				m_StartBPS[i] = bytes[i];
			
//			TRACE("average d(bytes) == %6d, d(t) == %.6f\n", bytes[i] - m_StartBPS[i], AveInterval);
		}

		m_LastInterval = AveInterval;
	}

	double Interval = (now.time - m_LastTime.time) + (now.millitm - m_LastTime.millitm) / 1000.0;
	
	if (Interval > 0)
	{
		for (short i = 0; i < 2; i++)
		{
//			TRACE("inst.   d(bytes) == %6d, d(t) == %.6f\n", bytes[i] - m_LastBPS[i], Interval);
			
			// Calculate bytes and bps for this sample period
			DWORD MeasuredBytes = bytes[i] - m_LastBPS[i];
			DWORD AdjustedBytes = MeasuredBytes + m_Overflow[i];
			double MeasuredBps = MeasuredBytes / Interval;
			double AdjustedBps = AdjustedBytes / Interval;

			// Calculate this sample's overflow (will be added into next sample)
			if (AdjustedBps > m_ByteRate)
			{
				m_Overflow[i] = round((AdjustedBps - m_ByteRate) * Interval);
				AdjustedBps = m_ByteRate;				
			}
			else
			{
				m_Overflow[i] = 0;
			}
	
			m_BPS[i] = round (AdjustedBps);
			m_FPS[i] = round ((frames[i] - m_LastFPS[i]) / Interval) ;

			m_LU[i] = round (100.0 * AdjustedBps / m_ByteRate) ;
//			TRACE("m_LU[%d] = %d, Overflow %d\n", i, m_LU[i], m_Overflow[i]);

			m_LastFPS[i] = frames[i];
			m_LastBPS[i] = bytes[i];
		}
		m_LastTime = now;
	}

	HandleOverflow (m_WanStats, m_ClearWanStats);
}


/////////////////////////////////////////////////////////////////////////////
// CFRStatDoc

IMPLEMENT_DYNCREATE(CFRStatDoc, CStatDoc)

CFRStatDoc::CFRStatDoc() : CStatDoc()
{
	m_RtC = RUNTIME_CLASS(CFRStatView);
}

BOOL CFRStatDoc::OnNewDocument()
{
	if (!CStatDoc::OnNewDocument())
		return FALSE;

	m_ClearLinkErrors = CFR_LINK_ERRORS();
	m_ClearLinkStats = CFR_LINK_STATS();
	m_ClearLMIStats = CFR_LMI_STATS();

	m_ProtocolErrors.RemoveAll();
	m_ClearInjManager.RemoveAll();

	for (short i = 0; i < m_pDataSource->GetNumCircuits(); i++) {
		m_ProtocolErrors.Add(new CFR_PROTOCOL_ERRORS());	
		m_PllStats.Add(new CFR_PLL_STATS());	
		m_InjManager.Add(new CFR_INJ_MANG());

		m_ClearProtocolErrors.Add(new CFR_PROTOCOL_ERRORS());	
		m_ClearPllStats.Add(new CFR_PLL_STATS());	
		m_ClearInjManager.Add(new CFR_INJ_MANG());
		}

	return TRUE;
}

void CFRStatDoc::ClearProtocolStats()
{
	CStatDoc::ClearProtocolStats();

	m_ClearLinkErrors = *(CFR_LINK_ERRORS *)GetStatType(typeid(CFR_LINK_ERRORS));
	m_ClearLinkStats = *(CFR_LINK_STATS *)GetStatType(typeid(CFR_LINK_STATS));
	m_ClearLMIStats = *(CFR_LMI_STATS *)GetStatType(typeid(CFR_LMI_STATS));

	for (short i = 0; i < m_pDataSource->GetNumCircuits(); i++) {
		*m_ClearProtocolErrors[i] = *(CFR_PROTOCOL_ERRORS *)GetStatType(typeid(CFR_PROTOCOL_ERRORS), i);
		*m_ClearPllStats[i] = *(CFR_PLL_STATS *)GetStatType(typeid(CFR_PLL_STATS), i);
		*m_ClearInjManager[i] = *(CFR_INJ_MANG *)GetStatType(typeid(CFR_INJ_MANG), i);
		}
}

void CFRStatDoc::GetProtocolStats()
{
	CStatDoc::GetProtocolStats();

	m_LinkErrors = *(CFR_LINK_ERRORS *)GetStatType(typeid(CFR_LINK_ERRORS));
	m_LinkStats = *(CFR_LINK_STATS *)GetStatType(typeid(CFR_LINK_STATS));
	m_LMIStats = *(CFR_LMI_STATS *)GetStatType(typeid(CFR_LMI_STATS));

	HandleOverflow(m_LinkErrors, m_ClearLinkErrors);
	HandleOverflow(m_LinkStats, m_ClearLinkStats);
	HandleOverflow(m_LMIStats, m_ClearLMIStats);

	CDWordArray Circuits;

	Circuits.SetSize(m_ClearPllStats.GetSize());
	UpdateAllViews(NULL, uavGetUpdateCircuits, &Circuits);

	for (short i = 0; i < Circuits.GetSize(); i++)
		if (Circuits[i] > 0)
			UpdateSelChange(i);
}

void CFRStatDoc::UpdateSelChange(int i)
{
	if (i < 0)
		return;

	*m_ProtocolErrors[i] = *(CFR_PROTOCOL_ERRORS *)GetStatType(typeid(CFR_PROTOCOL_ERRORS), i);
	*m_PllStats[i] = *(CFR_PLL_STATS *)GetStatType(typeid(CFR_PLL_STATS), i);
	*m_InjManager[i] = *(CFR_INJ_MANG *)GetStatType(typeid(CFR_INJ_MANG), i);

	HandleOverflow(*m_PllStats[i], *m_ClearPllStats[i]);
	HandleOverflow(*m_ProtocolErrors[i], *m_ClearProtocolErrors[i], (DWORD)_UI16_MAX);
	HandleOverflow(*m_InjManager[i], *m_ClearInjManager[i]);

	UpdateAllViews(NULL, uavUpdateStats);
}

void CFRStatDoc::SelChange(int index)
{
	UpdateSelChange(index);
	UpdateAllViews(NULL, uavUpdateStats);
}


//------------------------------------------------------------ MLZ 7/20/98 {
/////////////////////////////////////////////////////////////////////////////
// CHlcStatDoc

IMPLEMENT_DYNCREATE(CHlcStatDoc, CStatDoc)

CHlcStatDoc::CHlcStatDoc() : CStatDoc()
{
}

BOOL CHlcStatDoc::OnNewDocument()
{
	if (!CStatDoc::OnNewDocument())
		return FALSE;

	m_ClearDs1Status = CDS1_STATUS();
	m_ClearDs1ExtStatus = CDS1_EXT_STATUS();

	m_ClearBriStatus = CBRI_STATUS();

	m_ModemStatus.RemoveAll();
	m_ClearModemStatus.RemoveAll();

	m_ModemExtStatus.RemoveAll();
	m_ClearModemExtStatus.RemoveAll();

	for (short i = 0; i < m_pDataSource->GetNumCircuits(); i++) 
	{
		m_ModemStatus.Add(new CMODEM_STATUS());	
		m_ClearModemStatus.Add(new CMODEM_STATUS());	

//		m_ModemExtStatus.Add(new CMODEM_EXT_STATUS());	
//		m_ClearModemExtStatus.Add(new CMODEM_EXT_STATUS());	
	}

	return TRUE;
}

void CHlcStatDoc::ClearProtocolStats()
{
//	CStatDoc::ClearProtocolStats();

	m_ClearDs1Status    = *(CDS1_STATUS *)GetStatType(typeid(CDS1_STATUS));
	m_ClearDs1ExtStatus = *(CDS1_EXT_STATUS *)GetStatType(typeid(CDS1_EXT_STATUS));

	m_ClearBriStatus = *(CBRI_STATUS *)GetStatType(typeid(CBRI_STATUS));

	for (short i = 0; i < m_pDataSource->GetNumCircuits(); i++) 
	{
		*m_ClearModemStatus[i] = *(CMODEM_STATUS *)GetStatType(typeid(CMODEM_STATUS), i);
//		*m_ClearModemExtStatus[i] = *(CMODEM_EXT_STATUS *)GetStatType(typeid(CMODEM_EXT_STATUS), i);
	}
}

void CHlcStatDoc::GetProtocolStats()
{

	m_Ds1Status = *(CDS1_STATUS *)GetStatType(typeid(CDS1_STATUS));

	m_Ds1ExtStatus = *(CDS1_EXT_STATUS *)GetStatType(typeid(CDS1_EXT_STATUS));
	HandleOverflowEx( m_Ds1ExtStatus.line_code_violations, m_ClearDs1ExtStatus.line_code_violations );
	HandleOverflowEx( m_Ds1ExtStatus.crc_error_count,      m_ClearDs1ExtStatus.crc_error_count );

	m_BriStatus = *(CBRI_STATUS *)GetStatType(typeid(CBRI_STATUS));
	HandleOverflowEx( m_BriStatus.loss_of_sync, m_ClearBriStatus.loss_of_sync );
	HandleOverflowEx( m_BriStatus.collisions,   m_ClearBriStatus.collisions );

	////////////////////////////////////////////////////////////remember to remove
	m_DChanExtStatus = *(CDCHAN_EXT_STATUS *)GetStatType(typeid(CDCHAN_EXT_STATUS));
	m_BriConfig = *(CBRI_CONFIG *)GetStatType(typeid(CBRI_CONFIG));
	//////////////////////////////////////////////////////////////////remember to remove


	CDWordArray Circuits;
	Circuits.SetSize(m_ClearModemStatus.GetSize());
	UpdateAllViews(NULL, uavGetUpdateCircuits, &Circuits);

	for (short i = 0; i < Circuits.GetSize(); i++)
		if (Circuits[i] > 0)
			UpdateSelChange(i);
}


void CHlcStatDoc::UpdateSelChange(int i)
{
	if (i < 0)
		return;

	*m_ModemStatus[i] = *(CMODEM_STATUS *)GetStatType(typeid(CMODEM_STATUS), i);
//	*m_ModemExtStatus[i] = *(CMODEM_EXT_STATUS *)GetStatType(typeid(CMODEM_EXT_STATUS), i);

	UpdateAllViews(NULL, uavUpdateStats);
}


void CHlcStatDoc::SelChange(int index)
{
	UpdateSelChange(index);
	UpdateAllViews(NULL, uavUpdateStats);
}


/////////////////////////////////////////////////////////////////////////////
// CPriStatDoc

IMPLEMENT_DYNCREATE(CPriStatDoc, CHlcStatDoc)

CPriStatDoc::CPriStatDoc() : CHlcStatDoc()
{
	m_RtC = RUNTIME_CLASS(CPriStatView);
}

/////////////////////////////////////////////////////////////////////////////
// CBriStatDoc

IMPLEMENT_DYNCREATE(CBriStatDoc, CHlcStatDoc)

CBriStatDoc::CBriStatDoc() : CHlcStatDoc()
{
	m_RtC = RUNTIME_CLASS(CBriStatView);
}

/////////////////////////////////////////////////////////////////////////////
// CModemStatDoc

IMPLEMENT_DYNCREATE(CModemStatDoc, CHlcStatDoc)

CModemStatDoc::CModemStatDoc() : CHlcStatDoc()
{
	m_RtC = RUNTIME_CLASS(CModemStatView);
}

//------------------------------------------------------------ MLZ 7/20/98 }

/////////////////////////////////////////////////////////////////////////////
// CSnaStatDoc

IMPLEMENT_DYNCREATE(CSnaStatDoc, CStatDoc)

CSnaStatDoc::CSnaStatDoc() : CStatDoc()
{
	m_RtC = RUNTIME_CLASS(CSnaStatView);
}

BOOL CSnaStatDoc::OnNewDocument()
{
	if (!CStatDoc::OnNewDocument())
		return FALSE;

	m_WanLineStatus = CWANLINESTATUS();

	return TRUE;
}

void CSnaStatDoc::ClearProtocolStats()
{
	CStatDoc::ClearProtocolStats();
	m_ClearWanLineStatus = *(CWANLINESTATUS *)GetStatType(typeid(CWANLINESTATUS));
}

void CSnaStatDoc::GetProtocolStats()
{
	CStatDoc::GetProtocolStats();

	m_WanLineStatus = *(CWANLINESTATUS *)GetStatType(typeid(CWANLINESTATUS));

//	HandleOverflow (m_WanLineStatus->wan_linestatus_stats,
//		m_ClearWanLineStatus->wan_linestatus_stats) ;
}

/////////////////////////////////////////////////////////////////////////////
// CX25StatDoc

IMPLEMENT_DYNCREATE(CX25StatDoc, CStatDoc)

CX25StatDoc::CX25StatDoc() : CStatDoc()
{
	m_RtC = RUNTIME_CLASS(CX25StatView);
}

BOOL CX25StatDoc::OnNewDocument()
{
	if (!CStatDoc::OnNewDocument())
		return FALSE;

	m_ClearLapbStats = CLAPB();
	m_ClearX25Stats = CX25();

	return TRUE;
}

void CX25StatDoc::ClearProtocolStats()
{
	CStatDoc::ClearProtocolStats();

	m_ClearLapbStats = *(CLAPB *)GetStatType(typeid(CLAPB));
	m_ClearX25Stats = *(CX25 *)GetStatType(typeid(CX25));
}

void CX25StatDoc::GetProtocolStats()
{
	CStatDoc::GetProtocolStats();

	m_LapbStats = *(CLAPB *)GetStatType(typeid(CLAPB));
	m_X25Stats = *(CX25 *)GetStatType(typeid(CX25));

	HandleOverflow(m_LapbStats, m_ClearLapbStats);
	HandleOverflow(m_X25Stats, m_ClearX25Stats);
}

/////////////////////////////////////////////////////////////////////////////
// CTraceDoc

IMPLEMENT_DYNCREATE(CTraceDoc, CDocument)

CTraceDoc::CTraceDoc()
{
}

BOOL CTraceDoc::OnNewDocument()
{
	if (!CDocument::OnNewDocument())
		return FALSE;

	SetTitle("Summary");
	return TRUE;
}

CTraceDoc::~CTraceDoc()
{
}


BEGIN_MESSAGE_MAP(CTraceDoc, CDocument)
	//{{AFX_MSG_MAP(CTraceDoc)
	ON_UPDATE_COMMAND_UI(ID_FILE_SAVE, OnUpdateFileSave)
	ON_UPDATE_COMMAND_UI(ID_FILE_CLOSE, OnUpdateFileClose)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CTraceDoc diagnostics

#ifdef _DEBUG
void CTraceDoc::AssertValid() const
{
	CDocument::AssertValid();
}

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

/////////////////////////////////////////////////////////////////////////////
// CTraceDoc serialization

void CTraceDoc::Serialize(CArchive& ar)
{
	if (ar.IsStoring())
	{
		// TODO: add storing code here
	}
	else
	{
		// TODO: add loading code here
	}
}

/////////////////////////////////////////////////////////////////////////////
// CTraceDoc commands

void CStatDoc::OnUpdateFileSave(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
	pCmdUI->Enable(FALSE);
}

void CTraceDoc::OnUpdateFileSave(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
	pCmdUI->Enable(FALSE);
}

BOOL CTraceDoc::CanCloseFrame(CFrameWnd*) 
{
	// TODO: Add your specialized code here and/or call the base class
	POSITION pos = GetFirstViewPosition();
	ASSERT(pos != NULL);
	CView *pView = GetNextView(pos);

	return pView->GetParentFrame()->m_nWindow > 0;
}

void CTraceDoc::OnIdle()
{
	UpdateAllViews(NULL, uavUpdateIdle);
}

void CTraceDoc::OnUpdateFileClose(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
	pCmdUI->Enable(FALSE);	
}

/////////////////////////////////////////////////////////////////////////////
// CPPPStatDoc

IMPLEMENT_DYNCREATE(CPPPStatDoc, CStatDoc)

CPPPStatDoc::CPPPStatDoc() : CStatDoc()
{
	m_RtC = RUNTIME_CLASS(CPPPStatView);
}

BOOL CPPPStatDoc::OnNewDocument()
{
	if (!CStatDoc::OnNewDocument())
		return FALSE;

	m_WanLineStatus = CWANLINESTATUS();

	return TRUE;
}

void CPPPStatDoc::ClearProtocolStats()
{
	CStatDoc::ClearProtocolStats();
	m_ClearWanLineStatus = *(CWANLINESTATUS *)GetStatType(typeid(CWANLINESTATUS));
}

void CPPPStatDoc::GetProtocolStats()
{
	CStatDoc::GetProtocolStats();

	m_WanLineStatus = *(CWANLINESTATUS *)GetStatType(typeid(CWANLINESTATUS));
}


/////////////////////////////////////////////////////////////////////////////
// CPPPCsuStatDoc

IMPLEMENT_DYNCREATE(CPPPCsuStatDoc, CStatDoc)

CPPPCsuStatDoc::CPPPCsuStatDoc() : CStatDoc()
{
	m_RtC = RUNTIME_CLASS(CPPPCsuStatView);
}

void CPPPCsuStatDoc::ClearProtocolStats()
{
	CStatDoc::ClearProtocolStats();
	m_ClearRfc1406Stats = *(CRfc1406 *)GetStatType(typeid(CRfc1406));
	m_ClearIfaceState   = *(CIfaceState *)GetStatType(typeid(CIfaceState));
}

void CPPPCsuStatDoc::GetProtocolStats()
{
	CStatDoc::GetProtocolStats();

	m_Rfc1406Stats = *(CRfc1406 *)GetStatType(typeid(CRfc1406));
	m_IfaceState   = *(CIfaceState *)GetStatType(typeid(CIfaceState));
}


/////////////////////////////////////////////////////////////////////////////
// CFRCsuStatDoc
/////////////////////////////////////////////////////////////////////////////

IMPLEMENT_DYNCREATE(CFRCsuStatDoc, CStatDoc)

CFRCsuStatDoc::CFRCsuStatDoc() : CStatDoc()
{
	m_RtC = RUNTIME_CLASS(CFRCsuStatView);
}

BOOL CFRCsuStatDoc::OnNewDocument()
{
	if (!CStatDoc::OnNewDocument())
		return FALSE;

	m_ClearIfaceState = CIfaceState();
	m_ClearRfc1406Stats = CRfc1406();

	m_ClearLinkErrors = CFR_LINK_ERRORS();
	m_ClearLinkStats = CFR_LINK_STATS();
	m_ClearLMIStats = CFR_LMI_STATS();

	m_ProtocolErrors.RemoveAll();
	m_ClearInjManager.RemoveAll();

	for (short i = 0; i < m_pDataSource->GetNumCircuits(); i++) {
		m_ProtocolErrors.Add(new CFR_PROTOCOL_ERRORS());	
		m_PllStats.Add(new CFR_PLL_STATS());	
		m_InjManager.Add(new CFR_INJ_MANG());

		m_ClearProtocolErrors.Add(new CFR_PROTOCOL_ERRORS());	
		m_ClearPllStats.Add(new CFR_PLL_STATS());	
		m_ClearInjManager.Add(new CFR_INJ_MANG());
		}

	return TRUE;
}

void CFRCsuStatDoc::ClearProtocolStats()
{
	CStatDoc::ClearProtocolStats();

	m_ClearRfc1406Stats = *(CRfc1406 *)GetStatType(typeid(CRfc1406));
	m_ClearIfaceState = *(CIfaceState *)GetStatType(typeid(CIfaceState));

	m_ClearLinkErrors = *(CFR_LINK_ERRORS *)GetStatType(typeid(CFR_LINK_ERRORS));
	m_ClearLinkStats = *(CFR_LINK_STATS *)GetStatType(typeid(CFR_LINK_STATS));
	m_ClearLMIStats = *(CFR_LMI_STATS *)GetStatType(typeid(CFR_LMI_STATS));

	for (short i = 0; i < m_pDataSource->GetNumCircuits(); i++) {
		*m_ClearProtocolErrors[i] = *(CFR_PROTOCOL_ERRORS *)GetStatType(typeid(CFR_PROTOCOL_ERRORS), i);
		*m_ClearPllStats[i] = *(CFR_PLL_STATS *)GetStatType(typeid(CFR_PLL_STATS), i);
		*m_ClearInjManager[i] = *(CFR_INJ_MANG *)GetStatType(typeid(CFR_INJ_MANG), i);
		}
}

void CFRCsuStatDoc::GetProtocolStats()
{
	CStatDoc::GetProtocolStats();

	m_Rfc1406Stats = *(CRfc1406 *)GetStatType(typeid(CRfc1406));
	m_IfaceState = *(CIfaceState *)GetStatType(typeid(CIfaceState));

	m_LinkErrors = *(CFR_LINK_ERRORS *)GetStatType(typeid(CFR_LINK_ERRORS));
	m_LinkStats = *(CFR_LINK_STATS *)GetStatType(typeid(CFR_LINK_STATS));
	m_LMIStats = *(CFR_LMI_STATS *)GetStatType(typeid(CFR_LMI_STATS));

	HandleOverflow(m_LinkErrors, m_ClearLinkErrors);
	HandleOverflow(m_LinkStats, m_ClearLinkStats);
	HandleOverflow(m_LMIStats, m_ClearLMIStats);

	CDWordArray Circuits;

	Circuits.SetSize(m_ClearPllStats.GetSize());
	UpdateAllViews(NULL, uavGetUpdateCircuits, &Circuits);

	for (short i = 0; i < Circuits.GetSize(); i++)
		if (Circuits[i] > 0)
			UpdateSelChange(i);
}

void CFRCsuStatDoc::UpdateSelChange(int i)
{
	if (i < 0)
		return;

	*m_ProtocolErrors[i] = *(CFR_PROTOCOL_ERRORS *)GetStatType(typeid(CFR_PROTOCOL_ERRORS), i);
	*m_PllStats[i] = *(CFR_PLL_STATS *)GetStatType(typeid(CFR_PLL_STATS), i);
	*m_InjManager[i] = *(CFR_INJ_MANG *)GetStatType(typeid(CFR_INJ_MANG), i);

	HandleOverflow(*m_PllStats[i], *m_ClearPllStats[i]);
	HandleOverflow(*m_ProtocolErrors[i], *m_ClearProtocolErrors[i], (DWORD)_UI16_MAX);
	HandleOverflow(*m_InjManager[i], *m_ClearInjManager[i]);

	UpdateAllViews(NULL, uavUpdateStats);
}

void CFRCsuStatDoc::SelChange(int index)
{
	UpdateSelChange(index);
	UpdateAllViews(NULL, uavUpdateStats);
}


