//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.

#pragma once
#include "types.h"
#include "opcodes.h"
#include "updownclient.h"
#include "preferences.h"

class CUploadQueue{
public:
	CUploadQueue(CPreferences* in_prefs);
	~CUploadQueue();
	void	Process();
	void	AddClientToQueue(CUpDownClient* client,bool bIgnoreTimelimit = false, bool addInFirstPlace = false);
	bool	RemoveFromUploadQueue(CUpDownClient* client,bool updatewindow = true, bool earlyabort = false);
	bool	RemoveFromWaitingQueue(CUpDownClient* client,bool updatewindow = true);
	bool	IsOnUploadQueue(CUpDownClient* client)	{return GetWaitingClient(client);}
	bool	IsDownloading(CUpDownClient* client)	{return GetDownloadingClient(client);}

    void    UpdateDatarates();
	uint32	GetDatarate();
    uint32  GetToNetworkDatarate();

	bool	CheckForTimeOver(CUpDownClient* client);
	int		GetWaitingUserCount()					{return waitinglist.GetCount();}
	int		GetUploadQueueLength()					{return uploadinglist.GetCount();}
	int		GetActiveUploadsCount()					{return m_MaxActiveClientsShortTime;}
	void	UpdateBanCount();
	CUpDownClient*	GetWaitingClientByIP(uint32 dwIP);
	CUpDownClient*	GetNextClient(CUpDownClient* update);

	
	void	DeleteAll();
	uint16	GetWaitingPosition(CUpDownClient* client);
	void	SetBanCount(uint32 in_count)			{bannedcount = in_count;}
	uint32	GetBanCount()							{return bannedcount;}
	uint32	GetSuccessfullUpCount()					{return successfullupcount;}
	uint32	GetFailedUpCount()						{return failedupcount;}
	uint32	GetAverageUpTime();
	void	FindSourcesForFileById(CTypedPtrList<CPtrList, CUpDownClient*>* srclist, uchar* filehash);
	void	AddUpDataOverheadSourceExchange(uint32 data)	{ m_nUpDataRateMSOverhead += data;
															  m_nUpDataOverheadSourceExchange += data;
															  m_nUpDataOverheadSourceExchangePackets++;}
	void	AddUpDataOverheadFileRequest(uint32 data)		{ m_nUpDataRateMSOverhead += data;
															  m_nUpDataOverheadFileRequest += data;
															  m_nUpDataOverheadFileRequestPackets++;}
	void	AddUpDataOverheadServer(uint32 data)			{ m_nUpDataRateMSOverhead += data;
															  m_nUpDataOverheadServer += data;
															  m_nUpDataOverheadServerPackets++;}
	void	AddUpDataOverheadOther(uint32 data)				{ m_nUpDataRateMSOverhead += data;
															  m_nUpDataOverheadOther += data;
															  m_nUpDataOverheadOtherPackets++;}
	uint32	GetUpDatarateOverhead()						{return m_nUpDatarateOverhead;}
	uint64	GetUpDataOverheadSourceExchange()			{return m_nUpDataOverheadSourceExchange;}
	uint64	GetUpDataOverheadFileRequest()				{return m_nUpDataOverheadFileRequest;}
	uint64	GetUpDataOverheadServer()					{return m_nUpDataOverheadServer;}
	uint64	GetUpDataOverheadOther()					{return m_nUpDataOverheadOther;}
	uint64	GetUpDataOverheadSourceExchangePackets()	{return m_nUpDataOverheadSourceExchangePackets;}
	uint64	GetUpDataOverheadFileRequestPackets()		{return m_nUpDataOverheadFileRequestPackets;}
	uint64	GetUpDataOverheadServerPackets()			{return m_nUpDataOverheadServerPackets;}
	uint64	GetUpDataOverheadOtherPackets()				{return m_nUpDataOverheadOtherPackets;}
	void	CompUpDatarateOverhead();
    void    CUploadQueue::RemoveOrMoveDown(CUpDownClient* client);
protected:
	void	RemoveFromWaitingQueue(POSITION pos, bool updatewindow);
	POSITION	GetWaitingClient(CUpDownClient* client);
//	POSITION	GetWaitingClientByID(CUpDownClient* client);
	POSITION	GetDownloadingClient(CUpDownClient* client);
	bool		AcceptNewClient(uint32 numberOfUploads);
	bool		AddUpNextClient(CUpDownClient* directadd = 0, bool highPrioCheck = false);
private:
    CUpDownClient* CUploadQueue::FindBestClientInQueue();
    void CUploadQueue::InsertInUploadingList(CUpDownClient* newclient);
    void CUploadQueue::RemoveLowestFromWaitinglist();
    float CUploadQueue::GetAverageCombinedFilePrioAndCredit();

	CList<uint64,uint64> avarage_dr_list;
    CList<uint64,uint64> avarage_friend_dr_list;
	CList<DWORD,DWORD> avarage_tick_list;
	CList<int,int> activeClients_list;
    CList<DWORD,DWORD> activeClients_tick_list;
	CTypedPtrList<CPtrList, CUpDownClient*> waitinglist;
	CTypedPtrList<CPtrList, CUpDownClient*> uploadinglist;
	uint32	datarate;   //datarate of sent to network (excluding friends)
    uint32  friendDatarate; // datarate of sent to friends (included in above total)
	//uint32	dataratems;	// datarate last 100ms
	uint32	datarateave; //datarage average (since progstart) *unused*
	sint32	estadatarate; // esta. max datarate	
	CPreferences* app_prefs;
	UINT_PTR h_timer;
	uint32	bannedcount;
	uint32	successfullupcount;
	uint32	failedupcount;
	uint32	totaluploadtime;
    sint32  leftoverBandwidth;
    uint32  m_MaxActiveClients;
    uint32  m_MaxActiveClientsShortTime;

    uint32	m_nLastStartUpload;
	uint32	m_nUpDatarateOverhead;
	uint32	m_nUpDataRateMSOverhead;
	uint64	m_nUpDataOverheadSourceExchange;
	uint64	m_nUpDataOverheadFileRequest;
	uint64	m_nUpDataOverheadServer;
	uint64	m_nUpDataOverheadOther;
	uint64	m_nUpDataOverheadSourceExchangePackets;
	uint64	m_nUpDataOverheadFileRequestPackets;
	uint64	m_nUpDataOverheadServerPackets;
	uint64	m_nUpDataOverheadOtherPackets;
	uint32	m_nSumForAvgDataRate;
	CList<int,int>	m_AvarageUDRO_list;

    uint32  m_guessedMaxBandwidth;
    DWORD   m_lastGaveDataTick;
    DWORD   m_lastCalculatedDataRateTick;
    DWORD   m_dwLastCheckedForHighPrioClient;
    DWORD   m_dwLastExtremeUploadAmountTick;

    DWORD   m_dwLastCalculatedAverageCombinedFilePrioAndCredit;
    float   m_fAverageCombinedFilePrioAndCredit;
};
