/*----------------------------------------------------------
  PROJECT		: mldkgui

  FILE			: cMLDonkeyStatus.cpp
  VERSION		: 1.0

  CREATION		: 08.03.2004
  AUTHOR		: JLac
  LANGUAGE		: cpp
  AIM			: implementation of the cMLDonkeyStatus class.

  HISTORIC  	: -

-----------------------------------------------------------*/
#include <list> 
#include <vector> 
#include <string> 

using namespace std;

#include "typedef.h"
#include "cFileInfo.h"
#include "cStreamData.h"
#include "cNetworkInfo.h"

#include "cServerInfo.h"
#include "cLstServerInfo.h"
#include "cMLDonkeyStatus.h"

#include "LogMsg.h"


#define SIZE_OF_OPCODE	2
#define SIZE_OF_WORD32	4


enum {SIZE_OF_MESSAGE , MESSAGE};

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

/*******************************************************************
 *              
 *  FUNCTION:   cMLDonkeyStatus
 *              
 *  RETURNS:    -
 *              
 *  PARAMETERS: 
 *		Input  :
 *          -
 *
 *		Output :
 *              
 *  COMMENTS:   -
 *              
 *******************************************************************/
cMLDonkeyStatus::cMLDonkeyStatus()
{
	m_iNbDownloadingFiles = 0;
	m_iNbOption = 0;
	
	m_NextContentSize = SIZE_OF_WORD32;
	m_StatusOfNextRead = SIZE_OF_MESSAGE;

	TotalUploaded=0;
	TotalDownloaded=0;  
	TotalShared=0;  
	NumberOfSharedFiles=0;  
	TcpUploadRate=0;  
	TcpDownloadRate=0;  
	UdpUploadRate=0;  
	UdpDownloadRate=0;  
	NumberOfCurrentDownloads=0;
	NumberOfDownloadsFinished=0;  

}

/*******************************************************************
 *              
 *  FUNCTION:   ~cMLDonkeyStatus
 *              
 *  RETURNS:    -
 *              
 *  PARAMETERS: 
 *		Input  :
 *          -
 *
 *		Output :
 *              
 *  COMMENTS:   -
 *              
 *******************************************************************/
cMLDonkeyStatus::~cMLDonkeyStatus()
{
	cNetworkInfo *pNet;

	m_lstOption.clear();
	m_lstNetwordInfo.clear();
	m_lstDownloadingFiles.clear();

}

/*DS****************************************************************
 *              
 *  FUNCTION:   Analyse
 *              
 *  RETURNS:    -
 *              
 *  PARAMETERS: 
 *		Input  :
 *          Word8 *buf,Word32 size
 *
 *		Output :
 *              
 *  COMMENTS:   -
 *              
 *******************************************************************/
void cMLDonkeyStatus::Analyse(Word8 *buf,Word32 size)
{
	Word32 i,j;
	Word16 opcode;
	string strig1,strig2;

	Word32 ServerId,ServerRank;
	Word8 ServerState;

    m_cInputStream.Add(buf,size);

    while( m_cInputStream.IsEnoughDataAvailable(m_NextContentSize) )
	{
		LogMsg(LOGLEVEL_MAIN,"MlDkGUI : m_cInputStream.IsEnoughDataAvailable true : %d \n",m_StatusOfNextRead);

		switch(m_StatusOfNextRead)
		{
			case SIZE_OF_MESSAGE:
				m_NextContentSize = m_cInputStream.ReadWord32();
				m_StatusOfNextRead = MESSAGE;
				break;

			case MESSAGE:
					m_cInputStream.GetPos();

					opcode = m_cInputStream.ReadWord16();
					LogMsg(LOGLEVEL_MAIN,"MlDkGUI : cMLDonkeyStatus::Analyse Opcode:%d\n",opcode);
					switch(opcode)
					{
						case OPCODES_FROM_CORE_COREPROTOCOL:					// CoreProtocol
							m_iProtocolVersion = m_cInputStream.ReadWord32();			
							break;	

						case OPCODES_FROM_CORE_NETWORKINFO:						// NetworkInfo 
							AddNetworkInfo();
							break;	

						case OPCODES_FROM_CORE_CONSOLEMESSAGE:
							m_cInputStream.ReadString(MessageCore);
							break;

						case OPCODES_FROM_CORE_OPTIONSINFO:
							m_iNbOption = m_cInputStream.ReadWord16();
							for(i=0;i<m_iNbOption;i++)
							{
								strig1.erase();
								m_cInputStream.ReadString(strig1);
								strig2.erase();
								m_cInputStream.ReadString(strig2);
//								m_lstOption.insert(m_lstOption.end(), strig);
							}
															strig1.empty();

							break;

						case OPCODES_FROM_CORE_CLIENTSTATS:
							TotalUploaded = m_cInputStream.ReadWord64();
							TotalDownloaded = m_cInputStream.ReadWord64();
							TotalShared = m_cInputStream.ReadWord64();
							NumberOfSharedFiles = m_cInputStream.ReadWord32();
							TcpUploadRate = m_cInputStream.ReadWord32();
							TcpDownloadRate = m_cInputStream.ReadWord32();
							UdpUploadRate = m_cInputStream.ReadWord32();
							UdpDownloadRate = m_cInputStream.ReadWord32();
							NumberOfCurrentDownloads = m_cInputStream.ReadWord32();
							NumberOfDownloadsFinished = m_cInputStream.ReadWord32();
							j = m_cInputStream.ReadWord16();
							for(i=0;i<j;i++)
							{
								m_cInputStream.ReadWord32();
							}
							break;

						case OPCODES_FROM_CORE_DOWNLOADINGFILES:
							m_iNbDownloadingFiles = m_cInputStream.ReadWord16();

							LogMsg(LOGLEVEL_MAIN,"MlDkGUI : cMLDonkeyStatus::Analyse m_iNbDownloadingFiles=%d\n",m_iNbDownloadingFiles);

							for(i=0;i<m_iNbDownloadingFiles;i++)
							{
								AddDownloadingFiles();
							}
							break;


						case OPCODES_FROM_CORE_ADDSECTIONOPTION:
						case OPCODES_FROM_CORE_ADDPLUGINOPTION:
								strig1.erase();
								m_cInputStream.ReadString(strig1);
								strig2.erase();
								m_cInputStream.ReadString(strig2);
								strig1.erase();
								m_cInputStream.ReadString(strig1);
								m_cInputStream.ReadWord8();
							break;

						case OPCODES_FROM_CORE_SERVERSTATE:
							ServerId = m_cInputStream.ReadWord32();
							ServerState = m_cInputStream.ReadWord8();
							ServerRank = -1;
							if(ServerState == 5 || ServerState == 9)
								ServerRank = m_cInputStream.ReadWord32();
							m_lstServersInfo.UpdateStatusOfServer(ServerId,ServerState,ServerRank);
							break;

						case OPCODES_FROM_CORE_ROOMINFO:
						case OPCODES_FROM_CORE_ROOMINFO2:
							break;

						case OPCODES_FROM_CORE_SERVERINFO:
							AddServerInfo();
							break;

						case OPCODES_FROM_CORE_DEFINESEARCHES:
							LogMsg(LOGLEVEL_MAIN,"MlDkGUI : cMLDonkeyStatus::Analyse unknown Opcode:%d\n",opcode);
						case OPCODES_FROM_CORE_USERINFO:
							break;

 

						default:	// skip unknow opcode
					
							m_StatusOfNextRead = SIZE_OF_MESSAGE;
							;
					}
					m_cInputStream.SeekPos(m_NextContentSize);					// to assure a valid position
	
					m_NextContentSize = SIZE_OF_WORD32;
					m_StatusOfNextRead = SIZE_OF_MESSAGE;

				break;
		}
	}
}

/*DS****************************************************************
 *              
 *  FUNCTION:   AddNetworkInfo
 *              
 *  RETURNS:    -
 *              
 *  PARAMETERS: 
 *		Input  :
 *          -
 *
 *		Output :
 *              
 *  COMMENTS:   -
 *              
 *******************************************************************/
void cMLDonkeyStatus::AddNetworkInfo()
{
	cNetworkInfo *pNet;

	pNet = new cNetworkInfo;
	pNet->NetworkID = m_cInputStream.ReadWord32();
	m_cInputStream.ReadString(pNet->NetworkName);
	pNet->Enabled = m_cInputStream.ReadWord8();
	m_cInputStream.ReadString(pNet->NameOfNetworkConfigFile);
	pNet->NbBytesUploaded = m_cInputStream.ReadWord64();
	pNet->NbBytesDonloaded = m_cInputStream.ReadWord64();

//	m_lstNetwordInfo.push_back( *pNet );

	delete pNet;
}



/*******************************************************************
 *              
 *  FUNCTION:   PrepareMessage2Core
 *              
 *  RETURNS:    int
 *              
 *  PARAMETERS: 
 *		Input  :
 *          int msg,Word8 *buf,int sizemax
 *
 *		Output :
 *              
 *  COMMENTS:   -
 *              
 *******************************************************************/
int cMLDonkeyStatus::PrepareMessage2Core(int msg,Word8 *buf, int sizemax)
{
	Word32 taille = 0;
	Word32 pw = 4;

	switch(msg)
	{
		case OPCODES_TO_CORE_GUIPROTOCOLVERSION:
			buf[pw++] = OPCODES_TO_CORE_GUIPROTOCOLVERSION ;			taille ++;
			buf[pw++] = 0;			taille ++;

			buf[pw++] = 0x10;		taille ++;
			buf[pw++] = 0;			taille ++;
			buf[pw++] = 0;			taille ++;
			buf[pw++] = 0;			taille ++;

			break;

		case OPCODES_TO_CORE_SENDPASSWD:
			buf[pw++] = OPCODES_TO_CORE_SENDPASSWD;			taille ++;
			buf[pw++] = 0;			taille ++;

			buf[pw++] = 0;			taille ++;
			buf[pw++] = 0;			taille ++;
			buf[pw++] = 5;			taille ++;
			buf[pw++] = 0;			taille ++;

			buf[pw++] = 'a';			taille ++;
			buf[pw++] = 'd';			taille ++;
			buf[pw++] = 'm';			taille ++;
			buf[pw++] = 'i';			taille ++;
			buf[pw++] = 'n';			taille ++;
			
			break;	

		case OPCODES_TO_CORE_GETDOWNLOADINGFILES:
			buf[pw++] = OPCODES_TO_CORE_GETDOWNLOADINGFILES;			taille ++;
			buf[pw++] = 0;			taille ++;
			break;	

		case OPCODES_TO_CORE_GETCONNECTEDSERVERS:
			buf[pw++] = OPCODES_TO_CORE_GETCONNECTEDSERVERS;			taille ++;
			buf[pw++] = 0;			taille ++;
			break;	
	}

	/* ajoute la taille */
	buf[0] = taille & 0xff;
	buf[1] = (taille>>8) & 0xff;
	buf[2] = (taille>>16) & 0xff;
	buf[3] = (taille>>24) & 0xff;

	return(pw);
}

/*******************************************************************
 *              
 *  FUNCTION:   AddDownloadingFiles
 *              
 *  RETURNS:    void
 *              
 *  PARAMETERS: 
 *		Input  :
 *          -
 *
 *		Output :
 *              
 *  COMMENTS:   -
 *              
 *******************************************************************/
void cMLDonkeyStatus::AddDownloadingFiles()
{
	int i;
	string strg;
	cFileInfo fileInfo;
	
	fileInfo.FileIdentifier = m_cInputStream.ReadWord32();
	fileInfo.FileNetworkIdentifier = m_cInputStream.ReadWord32();

	fileInfo.m_NbPossibleFileNames = m_cInputStream.ReadWord16();
	for(i=0; i<fileInfo.m_NbPossibleFileNames ; i++)
	{
		strg.erase();
		m_cInputStream.ReadString(strg);
		fileInfo.lstPossibleFileNames.insert( fileInfo.lstPossibleFileNames.end(), strg );
	}

	for(i=0; i<16; i++)
		fileInfo.FileMd4[i] = m_cInputStream.ReadWord8();

	fileInfo.FileSize = m_cInputStream.ReadWord32();
	fileInfo.FileDownloaded = m_cInputStream.ReadWord32();
	fileInfo.NumberOfSources = m_cInputStream.ReadWord32();
	fileInfo.NumberOfClients = m_cInputStream.ReadWord32();

	fileInfo.FileState = m_cInputStream.ReadWord8();
	if( fileInfo.FileState == 6 )
		m_cInputStream.ReadString(fileInfo.ReasonOfAbortion );

	m_cInputStream.ReadString(fileInfo.Chunks);
	m_cInputStream.ReadString(fileInfo.Availability);
	m_cInputStream.ReadString(fileInfo.DownloadRate);

	fileInfo.m_NbChunksAges = m_cInputStream.ReadWord16();
	for(i=0; i<fileInfo.m_NbChunksAges ; i++)
	{
		strg.erase();
		m_cInputStream.ReadString(strg);
		fileInfo.lstChunksAges.insert( fileInfo.lstChunksAges.end(), strg );
	}

	m_cInputStream.ReadString(fileInfo.TimeFileAge );

	fileInfo.FileFormat = m_cInputStream.ReadWord8();
	switch(fileInfo.FileFormat)
	{
		case 1:			// Generic Format 
			m_cInputStream.ReadString(fileInfo.FormatExtension);
			m_cInputStream.ReadString(fileInfo.Formatkind);
			break;

		case 2:			// Avi File
			m_cInputStream.ReadString(fileInfo.VideoCodec);
			fileInfo.VideoWidth  = m_cInputStream.ReadWord32();
			fileInfo.VideoHeight  = m_cInputStream.ReadWord32();
			fileInfo.VideoFPS	= m_cInputStream.ReadWord32();
			fileInfo.VideoRate  = m_cInputStream.ReadWord32();
			break;

		case 3:			// Mp3 File 
			m_cInputStream.ReadString(fileInfo.Mp3Title);
			m_cInputStream.ReadString(fileInfo.Mp3Artist);
			m_cInputStream.ReadString(fileInfo.Mp3Album);
			m_cInputStream.ReadString(fileInfo.Mp3Year);
			m_cInputStream.ReadString(fileInfo.Mp3Comment);
			fileInfo.Mp3Tracknum	= m_cInputStream.ReadWord32();
			fileInfo.Mp3Genre  = m_cInputStream.ReadWord32();

			break;
	}

	m_cInputStream.ReadString(fileInfo.FilePreferredName );

	fileInfo.OffsetTime = m_cInputStream.ReadWord32();
	fileInfo.FilePriority= m_cInputStream.ReadWord32();

	m_lstDownloadingFiles.push_back(fileInfo);

}

/*******************************************************************
 *              
 *  FUNCTION:   AddServerInfo
 *              
 *  RETURNS:    void
 *              
 *  PARAMETERS: 
 *		Input  :
 *          -
 *
 *		Output :
 *              
 *  COMMENTS:   -
 *              
 *******************************************************************/
void cMLDonkeyStatus::AddServerInfo()
{
/*	int i;
	Word8	type;
	Word32	value;*/
	string  str;
	cServerInfo serverInfo;

	serverInfo.ServerID = m_cInputStream.ReadWord32();
	serverInfo.ServerNetworkID = m_cInputStream.ReadWord32();
	serverInfo.SrvAdrType = m_cInputStream.ReadWord8();
	if( serverInfo.SrvAdrType == 0 )
		serverInfo.SrvAdrIP = m_cInputStream.ReadWord32();
	else
		m_cInputStream.ReadString(serverInfo.SrvAdrName);

	serverInfo.ServerPort = m_cInputStream.ReadWord16();
	serverInfo.ServerScore = m_cInputStream.ReadWord32();

/*	serverInfo.NbTag = m_cInputStream.ReadWord16();
	for(i=0;i<serverInfo.NbTag;i++)
	{
		type = m_cInputStream.ReadWord8();
		serverInfo.TagType.push_back(type);
		value = 0;
		str.erase();
		if(type == 2)
			m_cInputStream.ReadString(str);
		else
			value=m_cInputStream.ReadWord32();

		serverInfo.TagValueInt.push_back(value);
		serverInfo.TagValueStr.push_back(str);
	}

	serverInfo.NumberOfUsers = m_cInputStream.ReadWord32();
	serverInfo.NumberOfFilesShared = m_cInputStream.ReadWord32();
	serverInfo.ConnectionState = m_cInputStream.ReadWord8();

	m_cInputStream.ReadString(serverInfo.ServerName);
	m_cInputStream.ReadString(serverInfo.ServerDescription);

	m_lstServersInfo.AddServerInfo(serverInfo);
*/
}
