//this file is part of eMule
//Copyright (C)2002 Merkur ( merkur-@users.sourceforge.net / http://www.emule-project.net )
//
//This program is free software; you can redistribute it and/or
//modify it under the terms of the GNU General Public License
//as published by the Free Software Foundation; either
//version 2 of the License, or (at your option) any later version.
//
//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with this program; if not, write to the Free Software
//Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

// StatisticsDlg.cpp : implementation file
//
#include "stdafx.h"
#include "emule.h"
#include "StatisticsDlg.h"
#include "uploadqueue.h"

// CStatisticsDlg dialog

IMPLEMENT_DYNAMIC(CStatisticsDlg, CDialog)
CStatisticsDlg::CStatisticsDlg(CWnd* pParent /*=NULL*/)
	: CResizableDialog(CStatisticsDlg::IDD, pParent) , m_DownloadOMeter( 3 ),m_Statistics(4),m_UploadOMeter(3)
{

}

CStatisticsDlg::~CStatisticsDlg()
{
}

void CStatisticsDlg::DoDataExchange(CDataExchange* pDX)
{
	CResizableDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CExoSliderDlg)
	DDX_Control(pDX, IDC_STATTREE, stattree);
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CStatisticsDlg, CResizableDialog)
	//{{AFX_MSG_MAP(CStatisticsDlg)
	ON_WM_SHOWWINDOW()
	ON_WM_SIZE()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()


// CStatisticsDlg message handlers

BOOL CStatisticsDlg::OnInitDialog(){

	CResizableDialog::OnInitDialog();
	EnableWindow( FALSE );

	Localize();

	// setup tree
	h_transfer= stattree.InsertItem(GetResString(IDS_FSTAT_TRANSFER));
	tran0= stattree.InsertItem(GetResString(IDS_FSTAT_WAITING),h_transfer);

	h_upload = stattree.InsertItem(GetResString(IDS_TW_UPLOADS), h_transfer);
	up1= stattree.InsertItem(GetResString(IDS_FSTAT_WAITING),h_upload);
	up2= stattree.InsertItem(GetResString(IDS_FSTAT_WAITING),h_upload);
	up3= stattree.InsertItem(GetResString(IDS_FSTAT_WAITING),h_upload);
	up4= stattree.InsertItem(GetResString(IDS_FSTAT_WAITING),h_upload);
	up5= stattree.InsertItem(GetResString(IDS_FSTAT_WAITING),h_upload);
	up6= stattree.InsertItem(GetResString(IDS_FSTAT_WAITING),h_upload);

	h_download = stattree.InsertItem(GetResString(IDS_TW_DOWNLOADS), h_transfer);
	down1= stattree.InsertItem(GetResString(IDS_FSTAT_WAITING),h_download);
	down2= stattree.InsertItem(GetResString(IDS_FSTAT_WAITING),h_download);
	down3= stattree.InsertItem(GetResString(IDS_FSTAT_WAITING),h_download);

	h_connection = stattree.InsertItem(GetResString(IDS_FSTAT_CONNECTION));
	con1= stattree.InsertItem(GetResString(IDS_FSTAT_WAITING),h_connection);
	con2= stattree.InsertItem(GetResString(IDS_FSTAT_WAITING),h_connection);
	con12= stattree.InsertItem(GetResString(IDS_FSTAT_WAITING),h_connection);
	con13= stattree.InsertItem(GetResString(IDS_FSTAT_WAITING),h_connection);
	con3= stattree.InsertItem(GetResString(IDS_FSTAT_WAITING),h_connection);
	con4= stattree.InsertItem(GetResString(IDS_FSTAT_WAITING),h_connection);
	con5= stattree.InsertItem(GetResString(IDS_FSTAT_WAITING),h_connection);
	con6= stattree.InsertItem(GetResString(IDS_FSTAT_WAITING),h_connection);
	con7= stattree.InsertItem(GetResString(IDS_FSTAT_WAITING),h_connection);
	con8= stattree.InsertItem(GetResString(IDS_FSTAT_WAITING),h_connection);
	con9= stattree.InsertItem(GetResString(IDS_FSTAT_WAITING),h_connection);

	h_clients = stattree.InsertItem(GetResString(IDS_CLIENTS));
	cli1= stattree.InsertItem(GetResString(IDS_FSTAT_WAITING),h_clients);
		cli_versions[0]= stattree.InsertItem(GetResString(IDS_FSTAT_WAITING),cli1);
		cli_versions[1]= stattree.InsertItem(GetResString(IDS_FSTAT_WAITING),cli1);
		cli_versions[2]= stattree.InsertItem(GetResString(IDS_FSTAT_WAITING),cli1);
		cli_versions[3]= stattree.InsertItem(GetResString(IDS_FSTAT_WAITING),cli1);

	cli2= stattree.InsertItem(GetResString(IDS_FSTAT_WAITING),h_clients);
		cli_versions[4]= stattree.InsertItem(GetResString(IDS_FSTAT_WAITING),cli2);
		cli_versions[5]= stattree.InsertItem(GetResString(IDS_FSTAT_WAITING),cli2);
		cli_versions[6]= stattree.InsertItem(GetResString(IDS_FSTAT_WAITING),cli2);
		cli_versions[7]= stattree.InsertItem(GetResString(IDS_FSTAT_WAITING),cli2);

	cli3= stattree.InsertItem(GetResString(IDS_FSTAT_WAITING),h_clients);
	cli4= stattree.InsertItem(GetResString(IDS_FSTAT_WAITING),h_clients);

	h_servers = stattree.InsertItem(GetResString(IDS_FSTAT_SERVERS));
	srv1= stattree.InsertItem(GetResString(IDS_FSTAT_WAITING),h_servers);
	srv2= stattree.InsertItem(GetResString(IDS_FSTAT_WAITING),h_servers);
	srv3= stattree.InsertItem(GetResString(IDS_FSTAT_WAITING),h_servers);
	srv4= stattree.InsertItem(GetResString(IDS_FSTAT_WAITING),h_servers);
	srv5= stattree.InsertItem(GetResString(IDS_FSTAT_WAITING),h_servers);
	srv6= stattree.InsertItem(GetResString(IDS_FSTAT_WAITING),h_servers);
	srv7= stattree.InsertItem(GetResString(IDS_FSTAT_WAITING),h_servers);
	srv8= stattree.InsertItem(GetResString(IDS_FSTAT_WAITING),h_servers);
	srv9= stattree.InsertItem(GetResString(IDS_FSTAT_WAITING),h_servers);

	h_shared = stattree.InsertItem( GetResString(IDS_SHAREDFILES) );
	shar1= stattree.InsertItem(GetResString(IDS_FSTAT_WAITING),h_shared);
	shar2= stattree.InsertItem(GetResString(IDS_FSTAT_WAITING),h_shared);
	shar3= stattree.InsertItem(GetResString(IDS_FSTAT_WAITING),h_shared);

	stattree.Expand(h_transfer,TVE_EXPAND);
	stattree.Expand(h_connection,TVE_EXPAND);
	stattree.Expand(h_clients,TVE_EXPAND);
	stattree.Expand(h_servers,TVE_EXPAND);
	stattree.Expand(h_shared ,TVE_EXPAND);
	stattree.Expand(h_upload,TVE_EXPAND);
	stattree.Expand(h_download,TVE_EXPAND);

	// Setup download-scope
	CRect rect;
	GetDlgItem(IDC_SCOPE_D)->GetWindowRect(rect) ;
	ScreenToClient(rect) ;
	m_DownloadOMeter.Create(WS_VISIBLE | WS_CHILD, rect, this) ; 
	m_DownloadOMeter.SetRange(0, theApp.glob_prefs->GetMaxGraphDownloadRate()+4, 0) ;
	m_DownloadOMeter.SetRange(0, theApp.glob_prefs->GetMaxGraphDownloadRate()+4, 1) ;
	m_DownloadOMeter.SetRange(0, theApp.glob_prefs->GetMaxGraphDownloadRate()+4, 2) ;

	m_DownloadOMeter.SetYUnits(GetResString(IDS_KBYTESEC)) ;
	//m_DownloadOMeter.SetXUnits(GetResString(IDS_TIME));

	// Setup upload-scope
	GetDlgItem(IDC_SCOPE_U)->GetWindowRect(rect) ;
	ScreenToClient(rect) ;
	m_UploadOMeter.Create(WS_VISIBLE | WS_CHILD, rect, this) ; 
	m_UploadOMeter.SetRange(0, theApp.glob_prefs->GetMaxGraphUploadRate()+4, 0) ;
	m_UploadOMeter.SetRange(0, theApp.glob_prefs->GetMaxGraphUploadRate()+4, 1) ;
	m_UploadOMeter.SetRange(0, theApp.glob_prefs->GetMaxGraphUploadRate()+4, 2) ;
	m_UploadOMeter.SetYUnits(GetResString(IDS_KBYTESEC)) ;
	//m_UploadOMeter.SetXUnits(GetResString(IDS_TIME));

	// Setup additional graph-scope
	GetDlgItem(IDC_STATSSCOPE)->GetWindowRect(rect) ;
	ScreenToClient(rect) ;
	m_Statistics.Create(WS_VISIBLE | WS_CHILD, rect, this) ; 
	m_Statistics.SetRanges(0, theApp.glob_prefs->GetStatsMax()) ;
	m_Statistics.autofitYscale=false;

	AddAnchor(IDC_STATIC_LINE,CSize(50,50));
	AddAnchor(IDC_STATTREE,CSize(50,50) ,CSize(100,100));
	AddAnchor(m_UploadOMeter,CSize(50,0) ,CSize(100,50));
	AddAnchor(m_DownloadOMeter,CSize(0,0) ,CSize(50,50));
	AddAnchor(m_Statistics,CSize(0,50) ,CSize(50,100));

	
	AddAnchor(IDC_C0,CSize(0,50));
	AddAnchor(IDC_C0_2,CSize(0,50));
	AddAnchor(IDC_C0_3,CSize(0,50));
	AddAnchor(IDC_C1,CSize(50,50));
	AddAnchor(IDC_C1_2,CSize(50,50));
	AddAnchor(IDC_C1_3,CSize(50,50));

	AddAnchor(IDC_S1,CSize(0,100));
	AddAnchor(IDC_S2,CSize(0,100));
	AddAnchor(IDC_S3,CSize(0,100));
	AddAnchor(IDC_S0,CSize(0,100));

	AddAnchor(IDC_STATIC_D3,CSize(0,50));
	AddAnchor(IDC_STATIC_U,CSize(50,50));
	AddAnchor(IDC_STATIC_D,CSize(0,50));
	AddAnchor(IDC_STATIC_U2,CSize(50,50));
	AddAnchor(IDC_STATIC_U3,CSize(50,50));
	AddAnchor(IDC_STATIC_D2,CSize(0,50));
	AddAnchor(IDC_STATIC_S2,CSize(0,100));
	AddAnchor(IDC_STATIC_S0,CSize(0,100));
	AddAnchor(IDC_STATIC_S1,CSize(0,100));
	AddAnchor(IDC_STATIC_S3,CSize(0,100));

	AddAnchor(IDC_TIMEAVG1,CSize(0,50));
	AddAnchor(IDC_TIMEAVG2,CSize(50,50));
	RepaintMeters();
	AddAnchor(m_Led1[0],CSize(0,50));
	AddAnchor(m_Led1[1],CSize(0,50));
	AddAnchor(m_Led1[2],CSize(0,50));
	AddAnchor(m_Led2[0],CSize(50,50));
	AddAnchor(m_Led2[1],CSize(50,50));
	AddAnchor(m_Led2[2],CSize(50,50));
	AddAnchor(m_Led3[0],CSize(0,100));
	AddAnchor(m_Led3[1],CSize(0,100));
	//AddAnchor(m_Led3[2],CSize(0,100));
	AddAnchor(m_Led3[3],CSize(0,100));

	m_Statistics.SetYUnits("") ;
	m_Statistics.SetXUnits(GetResString(IDS_TIME));

	RepaintMeters();
	m_Statistics.SetBackgroundColor(theApp.glob_prefs->GetStatsColor(0)) ;
	m_Statistics.SetGridColor(theApp.glob_prefs->GetStatsColor(1)) ;
	
	m_DownloadOMeter.InvalidateCtrl();
	m_UploadOMeter.InvalidateCtrl();
	m_Statistics.InvalidateCtrl();

	if (theApp.glob_prefs->GetStatsInterval()==0) GetDlgItem(IDC_STATTREE)->EnableWindow(false);

	UpdateData(FALSE);

	EnableWindow( TRUE );

	m_ilastMaxConnReached = 0;
	peakconnections = 0;
	totalconnectionchecks = 0;
	averageconnections = 0;
	activeconnections = 0;
	maxDown=0;
	maxDownavg=0;

	return true;
}

void CStatisticsDlg::SetupLegend( int ResIdx, int ElmtIdx, int legendNr){
	CRect Rect;

	GetDlgItem( ResIdx )->GetWindowRect( Rect );
	ScreenToClient( Rect );
	
	if (legendNr==1){
		if (!m_Led1[ ElmtIdx ]) m_Led1[ ElmtIdx ].Create( WS_VISIBLE | WS_CHILD, Rect, this );
		m_Led1[ ElmtIdx ].SetBackgroundColor( m_DownloadOMeter.GetPlotColor( ElmtIdx ) );
		m_Led1[ ElmtIdx ].SetFrameColor( RGB( 0x00, 0x00, 0x00 ) );
	} else if (legendNr==2) {
		if (!m_Led2[ ElmtIdx ]) m_Led2[ ElmtIdx ].Create( WS_VISIBLE | WS_CHILD, Rect, this );
		m_Led2[ ElmtIdx ].SetBackgroundColor( m_UploadOMeter.GetPlotColor( ElmtIdx ) );
		m_Led2[ ElmtIdx ].SetFrameColor( RGB( 0x00, 0x00, 0x00 ) );
	} else if (legendNr==3){
		if (!m_Led3[ ElmtIdx ]) m_Led3[ ElmtIdx ].Create( WS_VISIBLE | WS_CHILD, Rect, this );
		m_Led3[ ElmtIdx ].SetBackgroundColor( m_Statistics.GetPlotColor( ElmtIdx ) );
		m_Led3[ ElmtIdx ].SetFrameColor( RGB( 0x00, 0x00, 0x00 ) );
	}
}

void CStatisticsDlg::RepaintMeters() {
	m_DownloadOMeter.SetBackgroundColor(theApp.glob_prefs->GetStatsColor(0)) ;
	m_DownloadOMeter.SetGridColor(theApp.glob_prefs->GetStatsColor(1)) ;
	m_DownloadOMeter.SetPlotColor( theApp.glob_prefs->GetStatsColor(4) ,0) ;
	m_DownloadOMeter.SetPlotColor( theApp.glob_prefs->GetStatsColor(3) ,1) ;
	m_DownloadOMeter.SetPlotColor( theApp.glob_prefs->GetStatsColor(2) ,2) ;

	m_UploadOMeter.SetBackgroundColor(theApp.glob_prefs->GetStatsColor(0)) ;
	m_UploadOMeter.SetGridColor(theApp.glob_prefs->GetStatsColor(1)) ;
	m_UploadOMeter.SetPlotColor( theApp.glob_prefs->GetStatsColor(7) ,0) ;
	m_UploadOMeter.SetPlotColor( theApp.glob_prefs->GetStatsColor(6) ,1) ;
	m_UploadOMeter.SetPlotColor( theApp.glob_prefs->GetStatsColor(5) ,2) ;

	m_Statistics.SetBackgroundColor(theApp.glob_prefs->GetStatsColor(0)) ;
	m_Statistics.SetGridColor(theApp.glob_prefs->GetStatsColor(1)) ;
	m_Statistics.SetPlotColor( theApp.glob_prefs->GetStatsColor(8),0) ;
	m_Statistics.SetPlotColor( theApp.glob_prefs->GetStatsColor(10),1) ;
	//m_Statistics.SetPlotColor( theApp.glob_prefs->GetStatsColor(10),2) ;
	m_Statistics.SetPlotColor( theApp.glob_prefs->GetStatsColor(9),3) ;

	SetupLegend( IDC_C0_2, 0 ,1);
	SetupLegend( IDC_C0_3, 1 ,1);
	SetupLegend( IDC_C0,   2 ,1);
	
	SetupLegend( IDC_C1_2, 0 ,2 );
	SetupLegend( IDC_C1_3, 1 ,2 );
	SetupLegend( IDC_C1,   2 ,2 );
	

	SetupLegend( IDC_S0, 0 ,3);
	SetupLegend( IDC_S1, 1 ,3);
	//SetupLegend( IDC_S2, 2 ,3);
	SetupLegend( IDC_S3, 3 ,3);
}

void CStatisticsDlg::SetCurrentRate(float uploadrate, float downloadrate) {
	double m_dPlotDataUp[ 3 ];
	double m_dPlotDataDown[ 3 ];
	int myStats[6];

	// current rate
	m_dPlotDataDown[2]=downloadrate;
	m_dPlotDataUp[2]=uploadrate;
	
	if (maxDown<downloadrate) maxDown=downloadrate;
	
	// averages
	m_dPlotDataDown[0]=	GetAvgDownloadRate(AVG_SESSION);
	m_dPlotDataUp[0]=	GetAvgUploadRate(AVG_SESSION);

	m_dPlotDataDown[1]=	GetAvgDownloadRate(AVG_TIME);
	m_dPlotDataUp[1]=	GetAvgUploadRate(AVG_TIME);

	// show
	m_DownloadOMeter.AppendPoints(m_dPlotDataDown);
	m_UploadOMeter.AppendPoints(m_dPlotDataUp);


	// get Partialfiles summary
	activeconnections = theApp.listensocket->GetOpenSockets();
	UpdateConnectionsStatus();

	theApp.downloadqueue->GetDownloadStats(myStats);
	m_dPlotDataMore[0]=(activeconnections/3);//myStats[0];
	m_dPlotDataMore[1]=theApp.uploadqueue->GetUploadQueueLength();
	m_dPlotDataMore[2]=0;//theApp.uploadqueue->GetWaitingUserCount();
	m_dPlotDataMore[3]=myStats[1];

	//for (int i=0;i<4;i++) if (m_dPlotDataMore[i]>theApp.glob_prefs->GetStatsMax()) {resize=true;theApp.glob_prefs->GetStatsMax()=(int)m_dPlotDataMore[i];}
	//if (resize) m_Statistics.SetRanges(0, theApp.glob_prefs->GetStatsMax()+15) ;
	 
	m_Statistics.AppendPoints(m_dPlotDataMore);
}

void CStatisticsDlg::UpdateConnectionsStatus(){
	if( peakconnections < activeconnections )
		peakconnections = activeconnections;
	if( theApp.serverconnect->IsConnected() ){
	totalconnectionchecks++;
	float percent;
	percent = (float)((float)(totalconnectionchecks-1)/(float)totalconnectionchecks);
	if( percent > .999 )
		percent = (float).999;
	averageconnections = (averageconnections*percent) + (float)((float)activeconnections*(float)(1-percent));
	}
}

void CStatisticsDlg::RecordRate() {
	
	if (theApp.stat_transferStarttime==0) return;

	// every second
	downrateHistory.push_front(theApp.stat_sessionReceivedBytes);
	uprateHistory.push_front(theApp.stat_sessionSentBytes);
	
	// limit to maxmins 
	while ((int)downrateHistory.size()>(int)( theApp.glob_prefs->GetStatsAverageMinutes()*60)) downrateHistory.pop_back();
	while ((int)uprateHistory.size()>(int)( theApp.glob_prefs->GetStatsAverageMinutes()*60)) uprateHistory.pop_back();

}

void CStatisticsDlg::ShowStatistics() {
	char buffer[50];char buffer2[50];
	CString cbuffer;
	bool resize;
	DWORD running;
	int myStats[10];
	float DownAvgRate;

	resize=false;
	UpdateConnectionsStatus();
	theApp.downloadqueue->GetDownloadStats(myStats);

	CastItoXBytes( theApp.stat_sessionReceivedBytes ,buffer);
	CastItoXBytes( theApp.stat_sessionReceivedBytes+theApp.glob_prefs->GetTotalDownloaded() ,buffer2);
	cbuffer.Format(GetResString(IDS_STATS_DDATA),buffer,buffer2);
	stattree.SetItemText(down1, cbuffer);

	CastItoXBytes( theApp.stat_sessionSentBytes  ,buffer);
	CastItoXBytes( theApp.stat_sessionSentBytes+theApp.glob_prefs->GetTotalUploaded() ,buffer2);
	cbuffer.Format(GetResString(IDS_STATS_UDATA),buffer,buffer2);
	stattree.SetItemText(up1, cbuffer);

	if (theApp.stat_transferStarttime>0) {
		cbuffer.Format(GetResString(IDS_STATS_AVGDL),GetAvgDownloadRate(AVG_SESSION));
		stattree.SetItemText(con1, cbuffer);

		cbuffer.Format(GetResString(IDS_STATS_AVGUL),GetAvgUploadRate(AVG_SESSION));
		stattree.SetItemText(con2, cbuffer);

		DownAvgRate=GetAvgDownloadRate(AVG_SESSION);
		if (maxDownavg<DownAvgRate) maxDownavg=DownAvgRate;
		cbuffer.Format(GetResString(IDS_STATS_MAXAVGDL),maxDownavg);
		stattree.SetItemText(con12, cbuffer);
		cbuffer.Format(GetResString(IDS_STATS_MAXDL),maxDown);
		stattree.SetItemText(con13, cbuffer);
	}

	cbuffer.Format(GetResString(IDS_STATS_FOUNDSRC),myStats[0]);
	stattree.SetItemText(down2, cbuffer);

    cbuffer.Format(GetResString(IDS_STATS_ACTDL),myStats[1]);
	stattree.SetItemText(down3, cbuffer);
	cbuffer.Format(GetResString(IDS_STATS_ACTUL),theApp.uploadqueue->GetUploadQueueLength());
	stattree.SetItemText(up2, cbuffer);
	cbuffer.Format(GetResString(IDS_STATS_WAITINGUSERS),theApp.uploadqueue->GetWaitingUserCount());
	stattree.SetItemText(up3, cbuffer);
	cbuffer.Format(GetResString(IDS_STATS_SUCCUPCOUNT),theApp.uploadqueue->GetSuccessfullUpCount());
	stattree.SetItemText(up4, cbuffer);
	cbuffer.Format(GetResString(IDS_STATS_FAILUPCOUNT),theApp.uploadqueue->GetFailedUpCount());
	stattree.SetItemText(up5, cbuffer);
	running=theApp.uploadqueue->GetAverageUpTime();
	CastSecondsToHM(running,buffer);
	cbuffer.Format(GetResString(IDS_STATS_AVEUPTIME),buffer);
	stattree.SetItemText(up6, cbuffer);

	if (theApp.stat_reconnects>0) cbuffer.Format(GetResString(IDS_STATS_RECONNECTS),theApp.stat_reconnects-1);
		else cbuffer.Format(GetResString(IDS_STATS_RECONNECTS),0);
	stattree.SetItemText(con3, cbuffer);

	if (theApp.stat_transferStarttime==0) cbuffer.Format(GetResString(IDS_STATS_WAITTRANSF)); else {
		running=(GetTickCount()-theApp.stat_transferStarttime)/1000;
		CastSecondsToHM(running,buffer);
		cbuffer.Format(GetResString(IDS_TRANSFERTIME),buffer);
	}
	stattree.SetItemText(con4, cbuffer);

	if (theApp.stat_serverConnectTime==0) cbuffer.Format(GetResString(IDS_STATS_WAITCONN)); else {
		running=(GetTickCount()-theApp.stat_serverConnectTime)/1000;
		CastSecondsToHM(running,buffer);
		cbuffer.Format(GetResString(IDS_STATS_CONNECTEDSINCE),buffer);
	}
	stattree.SetItemText(con5, cbuffer);

	if (theApp.stat_sessionReceivedBytes>0 && theApp.stat_sessionSentBytes>0 )
		if (theApp.stat_sessionReceivedBytes<theApp.stat_sessionSentBytes) {
			cbuffer.Format(GetResString(IDS_STATS_RATIO)+" %.2f : 1",(float)theApp.stat_sessionSentBytes/theApp.stat_sessionReceivedBytes);
			stattree.SetItemText(tran0, cbuffer);
		} else {
			cbuffer.Format(GetResString(IDS_STATS_RATIO)+" 1 : %.2f",(float)theApp.stat_sessionReceivedBytes/theApp.stat_sessionSentBytes);
			stattree.SetItemText(tran0, cbuffer);
		}

	// shared files stats
	cbuffer.Format(GetResString(IDS_SHAREDFILESCOUNT),theApp.sharedfiles->GetCount());stattree.SetItemText(shar1, cbuffer);

	uint64 allsize=theApp.sharedfiles->GetDatasize();
	CastItoXBytes(allsize,buffer);

	cbuffer.Format(GetResString(IDS_SF_SIZE),buffer );stattree.SetItemText(shar2, cbuffer);
	
	if(theApp.sharedfiles->GetCount() != 0)
		CastItoXBytes((uint64)allsize/theApp.sharedfiles->GetCount(),buffer);
	else {
		buffer[0] = '-';
		buffer[1] = 0;
	}
	cbuffer.Format(GetResString(IDS_SF_AVERAGESIZE),buffer);stattree.SetItemText(shar3, cbuffer);
	// get clientversion-counts

	// statsclientstatus : original idea and code by xrmb
	CMap<uint8, uint8, uint32, uint32> clientStatus;
	CMap<uint8, uint8, uint32, uint32> clientVersionEDonkey;
	CMap<uint8, uint8, uint32, uint32> clientVersionEMule;
	uint32 totalclient;
	theApp.clientlist->GetStatistics(totalclient, myStats, &clientStatus, &clientVersionEDonkey, &clientVersionEMule);
	totalclient -= myStats[0];
	if( !totalclient )
		totalclient = 1;
	cbuffer.Format("eMule: %i(%1.1f%%)",myStats[2],(double)100*myStats[2]/totalclient);stattree.SetItemText(cli1, cbuffer);
	cbuffer.Format("eDonkey: %i(%1.1f%%)",myStats[1],(double)100*myStats[1]/totalclient);stattree.SetItemText(cli2, cbuffer);
	cbuffer.Format("Old MLDonkey: %i(%1.1f%%)",myStats[3],(double)100*myStats[3]/totalclient);stattree.SetItemText(cli3, cbuffer);
	cbuffer.Format(GetResString(IDS_STATS_UNKNOWNCLIENT),myStats[0]);stattree.SetItemText(cli4, cbuffer);

	if (stattree.GetItemState(cli2, TVIS_EXPANDED)&&TVIS_EXPANDED == TVIS_EXPANDED ) {

		uint32 totcnt = myStats[1];

		//--- find top 4 eDonkey client versions ---
		uint32	currtop = 0;
		uint32	lasttop = 0xFFFFFFFF;
		for(uint32 i=0; i<4; i++)
		{
			POSITION pos=clientVersionEDonkey.GetStartPosition();
			uint32 topver=0;
			uint32 topcnt=0;
			double topper=0;
			while(pos)
			{
				uint8	ver;
				uint32	cnt;
				clientVersionEDonkey.GetNextAssoc(pos, ver, cnt);
				if(currtop<ver && ver<lasttop && ver != 0x91)
				{
					double percent = (double)cnt/totcnt;
					if( lasttop == 0xFFFFFFFF &&
					    ( (totcnt > 75 && ((cnt <= 2) || percent < 0.01)) ||
					      (totcnt > 50 && cnt <= 1)
					    )
					  )
						continue;
					topper=percent;
					topver=ver;
					topcnt=cnt;
					currtop=ver;
				}
			}
			lasttop=currtop;
			currtop=0;
			if(topcnt)
				cbuffer.Format("v%i: %i (%1.1f%%)", topver, topcnt, topper*100);
			else
				cbuffer.Format("");

			stattree.SetItemText(cli_versions[i+4], cbuffer);
		}
	}

	if (stattree.GetItemState(cli1, TVIS_EXPANDED)&&TVIS_EXPANDED == TVIS_EXPANDED ) {
		uint32 totcnt = myStats[2];

		//--- find top 4 eMule client versions ---
		uint32	currtop = 0;
		uint32	lasttop = 0xFFFFFFFF;
		for(uint32 i=0; i<4; i++)
		{
			POSITION pos=clientVersionEMule.GetStartPosition();
			uint32 topver=0;
			uint32 topcnt=0;
			double topper=0;
			while(pos)
			{
				uint8	ver;
				uint32	cnt;
				clientVersionEMule.GetNextAssoc(pos, ver, cnt);
				if(currtop<ver && ver<lasttop && ver != 0x2B)
				{
					double percent = (double)cnt/totcnt;
					if( lasttop == 0xFFFFFFFF &&
					    ( (totcnt > 75 && ((cnt <= 2) || percent < 0.01)) ||
					      (totcnt > 50 && cnt <= 1)
					    )
					  )
						continue;
					topper=percent;
					topver=ver;
					topcnt=cnt;
					currtop=ver;
				}
			}
			lasttop=currtop;
			currtop=0;
			if(topcnt)
				cbuffer.Format("v0.%02X: %i (%1.1f%%)", topver, topcnt, topper*100);
			else
				cbuffer.Format("");

			stattree.SetItemText(cli_versions[i], cbuffer);
		}
		// xrmb
	}

	// get serverstats
	uint32 servtotal;
	uint32 servfail;
	uint32 servuser;
	uint32 servfile;
	uint32 servtuser;
	uint32 servtfile;
	float servocc;
	theApp.serverlist->GetStatus( servtotal, servfail, servuser, servfile, servtuser, servtfile,servocc);
	cbuffer.Format(GetResString(IDS_SF_WORKING)+": %i",servtotal-servfail);stattree.SetItemText(srv1, cbuffer);
	cbuffer.Format(GetResString(IDS_SF_FAIL)+": %i",servfail);stattree.SetItemText(srv2, cbuffer);
	cbuffer.Format(GetResString(IDS_SF_TOTAL)+": %i",servtotal);stattree.SetItemText(srv3, cbuffer);
	cbuffer.Format(GetResString(IDS_SF_DELCOUNT)+": %i",theApp.serverlist->GetDeletedServerCount());stattree.SetItemText(srv4, cbuffer);
	cbuffer.Format(GetResString(IDS_SF_WUSER)+": %i",servuser);stattree.SetItemText(srv5, cbuffer);
	cbuffer.Format(GetResString(IDS_SF_WFILE)+": %i",servfile);stattree.SetItemText(srv6, cbuffer);
	cbuffer.Format(GetResString(IDS_SF_USER)+": %i",servtuser);stattree.SetItemText(srv7, cbuffer);
	cbuffer.Format(GetResString(IDS_SF_FILE)+": %i",servtfile);stattree.SetItemText(srv8, cbuffer);
	cbuffer.Format(GetResString(IDS_SF_ACTIVECON)+": %i",activeconnections);stattree.SetItemText(con6, cbuffer);
	cbuffer.Format(GetResString(IDS_SF_SRVOCC),servocc);stattree.SetItemText(srv9, cbuffer);
	uint32 m_itemp = theApp.listensocket->GetMaxConnectionReached();
	if( m_itemp != m_ilastMaxConnReached ){
		char osDate[30],osTime[30];
		_strtime( osTime );
		_strdate( osDate );
		cbuffer.Format(GetResString(IDS_SF_MAXCONLIMITREACHED)+": %i : %s %s",m_itemp,osDate,osTime);stattree.SetItemText(con7, cbuffer);
		m_ilastMaxConnReached = m_itemp;
	}
	else if( m_itemp == 0 ){
		cbuffer.Format(GetResString(IDS_SF_MAXCONLIMITREACHED)+": %i",m_itemp);stattree.SetItemText(con7, cbuffer);}

	if(theApp.serverconnect->IsConnected()){
		cbuffer.Format(GetResString(IDS_SF_AVGCON)+": %i",(int)averageconnections);stattree.SetItemText(con8, cbuffer);
	}
	else{
		stattree.SetItemText(con8, GetResString(IDS_STATS_WAITCONN));
	}
	cbuffer.Format(GetResString(IDS_SF_PEAKCON)+": %i",peakconnections);stattree.SetItemText(con9, cbuffer);
}

float CStatisticsDlg::GetAvgDownloadRate(int averageType) {
	
	if (averageType==AVG_SESSION) {
		if (theApp.stat_transferStarttime ==0) return 0;

		DWORD running=(GetTickCount()-theApp.stat_transferStarttime)/1000;
		if (running<5) return 0;

		return (float)(theApp.stat_sessionReceivedBytes/1024) / running;
	} else {
		if (downrateHistory.size()==0) return 0;

		return (float)((float)((downrateHistory.front()-downrateHistory.back())/1024)/downrateHistory.size());
	}
}

float CStatisticsDlg::GetAvgUploadRate(int averageType) {
	if (averageType==AVG_SESSION) {
		if (theApp.stat_transferStarttime==0) return 0;

		DWORD running=(GetTickCount()-theApp.stat_transferStarttime)/1000;
		if (running<5) return 0;

		return (float)(theApp.stat_sessionSentBytes/1024) / running;
	} else  {
		if (uprateHistory.size()==0) return 0;

		return (float)((float)((uprateHistory.front()-uprateHistory.back())/1024)/uprateHistory.size());
	}

}

void CStatisticsDlg::OnShowWindow(BOOL bShow,UINT nStatus){

}

void CStatisticsDlg::OnSize(UINT nType, int cx, int cy)
{
	CResizableDialog::OnSize(nType, cx, cy);

}  //OnSize

void CStatisticsDlg::ShowInterval() {
	EnableWindow( FALSE );

	int shownSecs=518*theApp.glob_prefs->GetTrafficOMeterInterval();
	
	if (theApp.glob_prefs->GetTrafficOMeterInterval()==0) {
		m_DownloadOMeter.SetXUnits(GetResString(IDS_STOPPED)); 
		m_UploadOMeter.SetXUnits(GetResString(IDS_STOPPED)); 
	} else
	{
		char buffer[50];
		CastSecondsToHM(shownSecs,buffer);
		m_UploadOMeter.SetXUnits(buffer );
		m_DownloadOMeter.SetXUnits(buffer); 
	}

	UpdateData(FALSE);
	EnableWindow( TRUE );
}

void CStatisticsDlg::SetARange(bool SetDownload,int maxValue){
	if (SetDownload) {
		m_DownloadOMeter.SetRange(0, maxValue+4, 0);
		m_DownloadOMeter.SetRange(0, maxValue+4, 1);
		m_DownloadOMeter.SetRange(0, maxValue+4, 2);
	}else{
		m_UploadOMeter.SetRange(0, maxValue+4, 0) ;
		m_UploadOMeter.SetRange(0, maxValue+4, 1);
		m_UploadOMeter.SetRange(0, maxValue+4, 2);
	}
}

void CStatisticsDlg::Localize(){
	GetDlgItem(IDC_STATIC_D3)->SetWindowText(GetResString(IDS_ST_DOWNLOAD));
	GetDlgItem(IDC_STATIC_U)->SetWindowText(GetResString(IDS_ST_UPLOAD));
	GetDlgItem(IDC_STATIC_D)->SetWindowText(GetResString(IDS_ST_CURRENT));
	GetDlgItem(IDC_STATIC_U2)->SetWindowText(GetResString(IDS_ST_CURRENT));
	GetDlgItem(IDC_STATIC_D2)->SetWindowText(GetResString(IDS_ST_SESSION));
	GetDlgItem(IDC_STATIC_U3)->SetWindowText(GetResString(IDS_ST_SESSION));
	GetDlgItem(IDC_STATIC_S2)->SetWindowText(GetResString(IDS_ST_ACTIVED));
	GetDlgItem(IDC_STATIC_S0)->SetWindowText(GetResString(IDS_ST_ACTIVEC));
	GetDlgItem(IDC_STATIC_S1)->SetWindowText(GetResString(IDS_ST_ACTIVEU));
	GetDlgItem(IDC_STATIC_S3)->SetWindowText(GetResString(IDS_ST_WAITINGU));
	CString value;value.Format(" (%u %s)",theApp.glob_prefs->GetStatsAverageMinutes(),GetResString(IDS_MINS) );
	GetDlgItem(IDC_TIMEAVG1)->SetWindowText(GetResString(IDS_AVG) + value );
	GetDlgItem(IDC_TIMEAVG2)->SetWindowText(GetResString(IDS_AVG) + value);
}

