// GosStatPane.cpp : implementation file
//

#include "stdafx.h"
#include "GosView.h"
#include "GosStatPane.h"
#include "GosViewDoc.h"
#include "TimeFrame.h"

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

extern char *TimeToString( double secs );


/////////////////////////////////////////////////////////////////////////////
// CGosStatPane

IMPLEMENT_DYNCREATE(CGosStatPane, CView)

CGosStatPane::CGosStatPane()
{
}

CGosStatPane::~CGosStatPane()
{
}


BEGIN_MESSAGE_MAP(CGosStatPane, CView)
	//{{AFX_MSG_MAP(CGosStatPane)
	ON_WM_ERASEBKGND()
	ON_WM_VSCROLL()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CGosStatPane drawing

void CGosStatPane::OnDraw(CDC* pDC)
{
	CGosViewDoc* pDoc = (CGosViewDoc *)GetDocument();
	CTimeFrame *pFrame = m_pParentFrame;
	CTimeFrame::TagNode *pNode;
	DWORD id;

	if( !pDoc->TraceReady() )
		return;

	if( pDoc->m_pFont )
		pDC->SelectObject( pDoc->m_pFont );
	else
		pDC->SelectStockObject( ANSI_FIXED_FONT );


	/*
	switch( m_eStatMode )
	{
	case StatModeView:
		RecalcStats( m_pParentFrame->
	}
	*/
	_int64 tStart;
	_int64 tEnd;

	if( 0 )
	{
		tStart = pDoc->TLogStart();
		tEnd = pDoc->TLogEnd();
	}
	else
	{
		tStart = m_pParentFrame->m_tVisibleStart;
		tEnd = m_pParentFrame->m_tVisibleEnd;
	}

	RecalcStats( tStart, tEnd );

	TEXTMETRIC tm;
	pDC->GetTextMetrics(&tm);
	char stats1[15];
	char stats2[8];
	char stats3[15];

	pDC->SetBkMode( TRANSPARENT );

	UINT oldAlign = pDC->SetTextAlign(TA_RIGHT);

	for( id = pFrame->m_FirstID; id; id = pNode->idNextEnabled )
	{
		pNode = pFrame->AnyIDToTag(id);
		if( !pNode->independent )
			continue;
		if( pNode->onScreen )
		{
			int y = pNode->screenY - ( tm.tmHeight >> 1 );
			sprintf(stats1, "%8s",
				TimeToString((double)(pNode->sumTicks)/(double)pDoc->m_nFreq) );
			sprintf(stats2, "%%%.2lf",
				100.0 * (double)pNode->sumTicks / (double)(tEnd-tStart) );
			sprintf(stats3, "%3d",
				pNode->countEntry );


			pDC->TextOut( tm.tmAveCharWidth * 12, y, stats1 );
			pDC->TextOut( tm.tmAveCharWidth * 20, y, stats2 );
			pDC->TextOut( tm.tmAveCharWidth * 28, y, stats3 );
		}
	}

	pDC->SetTextAlign(oldAlign);

	pDC->SelectStockObject( ANSI_FIXED_FONT );


}

/////////////////////////////////////////////////////////////////////////////
// CGosStatPane diagnostics

#ifdef _DEBUG
void CGosStatPane::AssertValid() const
{
	CView::AssertValid();
}

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

/////////////////////////////////////////////////////////////////////////////
// CGosStatPane message handlers

BOOL CGosStatPane::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext) 
{
	// TODO: Add your specialized code here and/or call the base class

	//GetScrollBarCtrl(SB_HORZ)->ShowScrollBar(FALSE);	// hide the scroll bar!
	
	return CGosEventPane::Create(lpszClassName, lpszWindowName, dwStyle, rect, pParentWnd, nID, pContext);
}

void CGosStatPane::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
{
	// TODO: Add your message handler code here and/or call default
	
	CGosEventPane::OnVScroll(nSBCode, nPos, pScrollBar);
//	Invalidate();
}

BOOL CGosStatPane::OnEraseBkgnd(CDC* pDC) 
{
	// TODO: Add your message handler code here and/or call default
	
	return CGosEventPane::OnEraseBkgnd(pDC);
}

void CGosStatPane::RecalcStats( _int64 tStart, _int64 tEnd )
{
	CGosViewDoc* pDoc = (CGosViewDoc *)GetDocument();

	DWORD *pLogEntry;
	DWORD newTag;
	DWORD tag;
	DWORD time;
	DWORD oldTime;	// so tDiff = 0 first time
	DWORD tDiff;
	int left = 0;
	int right = 0;
	_int64 tRight = pDoc->TLogStart();
	_int64 tLeft;

	pLogEntry = pDoc->m_pLog;
	tag = *pLogEntry++;
	oldTime = *pLogEntry++;

	CTimeFrame::TagNode *pNode;

	for( pNode = m_pParentFrame->m_TagList.First();
		pNode;
		pNode = m_pParentFrame->m_TagList.Next(pNode) )
	{
		pNode->sumTicks = 0;
		pNode->countEntry = 0;
	}
	for( pNode = m_pParentFrame->m_ParentList.First();
		pNode;
		pNode = m_pParentFrame->m_ParentList.Next(pNode) )
	{
		pNode->sumTicks = 0;
		pNode->countEntry = 0;
	}

	for( ; pLogEntry < pDoc->m_pLogEnd; oldTime = time, tag = newTag )
	{
		newTag = *pLogEntry++;
		time = *pLogEntry++;
		tDiff = time - oldTime;
		tLeft = tRight;
		tRight += tDiff;

		if( tRight < tStart )	// entirely left of the valid range
			continue;

		if( tLeft < tStart )
		{
			// this entry straddles left of view
			tLeft = tStart;
			tag |= 0x00100000;	// make sure the entry isn't counted

		}

		CTimeFrame::TagNode *pNode = m_pParentFrame->m_TagList.Find(tag);

		if( pNode && pNode->pAssignTo )
		{
			if( !( tag & 0x00100000 ) )	// don't count if it was a return-to-tag entry
				pNode->pAssignTo->countEntry++;

			if( tRight > tEnd )
			{
				pNode->pAssignTo->sumTicks += ( tEnd - tLeft );
				break;
			}
		
			pNode->pAssignTo->sumTicks += ( tRight - tLeft );

		}
		else
		{
			if( tRight > tEnd )
				break;
		}
	}

}
