/***************************************************************************
                          ctransfer.h  -  description
                             -------------------
    begin                : Fri Feb 22 2002
    copyright            : (C) 2002-2004 by Mathias Küster
    email                : mathen@users.berlios.de
 ***************************************************************************/

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

#ifndef CTRANSFER_H
#define CTRANSFER_H

/**
  *@author Mathias Küster
  */

#include <dclib/dcos.h>
#include <dclib/core/cstring.h>
#include <dclib/core/ccallback.h>
#include <dclib/core/cfile.h>
#include <dclib/core/czlib.h>
#include <dclib/cdcproto.h>

#ifndef WIN32
#include <sys/time.h>
#endif

class CTransfer;
class CByteArray;

typedef enum eTransferState {
	etsNONE,
	etsREADY,
	etsIDLE
} eTransferState;

typedef enum eTransferType {
	ettNONE,
	ettSETTINGS,
	ettOPERATOR,
	ettUSER,
	ettSPECIAL
} eTransferType;

typedef struct sAverageTransferRate {
	struct timeval tv[10];
	ulonglong transfered[10];
	int index;
} sAverageTransferRate;

class DLL_EXPORT CTransfer : public CDCProto {
public:
	/** */
	CTransfer( bool listener = FALSE );
	/** */
	virtual ~CTransfer();

	/** callback function */
	virtual int DC_CallBack( CObject * ) { return -1; };
	/** */
	virtual void DataAvailable( const char * buffer, int len );
	/** */
	virtual void DataSend();
	/** */
	virtual void DataTimeout();
	/** */
	virtual void ConnectionState( eConnectionState state );
	/** */
	virtual void Notify();

	/** */
	void SetCallBackFunction( _CCallback * callback );

	/** */
	int StartDownload( CString dstfile, ulonglong startposition, ulonglong endposition, ulonglong size, ulonglong chunksize, CString srcfile );
	/** */
	int StartUpload( CString dstfile, ulonglong length, ulonglong pos, ulonglong chunksize, CString srcfile );

	/** */
	int CallBack_SendObject( CObject * Object );
	/** */
	int CallBack_SendError( CString msg );

	/** */
	ulonglong GetTransferrate();
	/** */
	ulonglong GetBytesForTransferrate( ulonglong rate );
	/** */
	void AddTraffic( long n );
	/** */
	ulonglong GetTraffic();

	/** */
	int HandleMessage( char * c, int len );

	/** */
	void CloseFile() { m_File.Close(); };
	/** */
	ulonglong GetTransferID() const;
	/** */
	void SetTransferID( ulonglong transferid );
	/** */
	CString GetDstFilename() const;
	/** */
	void SetDstFilename( CString filename );
	/** */
	CString GetSrcFilename() const;
	/** */
	void SetSrcFilename( CString filename );
	/** */
	CString GetDstNick() const;
	/** */
	CString GetHubHost() const;
	/** */
	void SetHubHost( CString hubhost );
	/** */
	CString GetHubName() const;
	/** */
	void SetHubName( CString hubname );
	/** */
	eltMedium GetMedium() const;
	/** */
	void SetMedium( eltMedium medium );
	/** */
	long GetBuffer( CByteArray *ba );
	/** */
	void SetBuffer( CByteArray *ba );

	/** */
	eDirection GetSrcDirection() const;
	/** */
	void SetSrcDirection( eDirection direction );
	/** */
	eDirection GetDstDirection() const;
	/** */
	void SetDstDirection( eDirection direction );

	/** */
	int GetSrcLevel() const;
	/** */
	int GetDstLevel() const;
	/** */
	eConnectionState GetMode() const;
	/** */
	void SetMode( eConnectionState mode );
	/** */
	ulonglong GetStartPosition() const;
	/** */
	void SetStartPosition( ulonglong pos );
	/** */
	ulonglong GetEndPosition() const;
	/** */
	void SetEndPosition( ulonglong pos );
	/** */
	ulonglong GetLength() const;
	/** */
	void SetLength( ulonglong length );
	/** */
	ulonglong GetTransfered() const;
	/** */
	void SetTransfered( ulonglong n ) { m_nTransfered = n; };
	/** */
	ulonglong GetChunkSize() const { return m_nChunkSize; };
	/** */
	void SetChunkSize( ulonglong n ) { m_nChunkSize = n; };
	/** */
	void InitTime();
	/** */
	void SetNick( CString nick );
	/** */
	CString GetNick();
	/** */
	void SetRate( ulonglong rate );
	/** */
	ulonglong GetRate() const;
	/** */
	bool IsIdle() const;

	/** */
	void SetDone( eTransferState e );
	/** */
	eTransferState GetDone() const;
	/** */
	time_t GetStartTime() const;
	/** */
	void SetStartTime( time_t t );

	/** */
	eTransferType GetTransferType() const;
	/** */
	void SetTransferType( eTransferType type );

	/** */
	CMessageSupports GetSupport() { return m_MessageSupports; }
	/** */
	bool GetEncrypted();

private:
	/** */
	bool DoInitDownload();
	/** */
	int HandleFileTransfer( const char * buffer, int len );
	/** */
	int HandleBufferTransfer( const char * buffer, int len );
	/** */
	int HandleControlTransfer( const char * buffer, int len );

	/** */
	int m_nDataType;
	/** */
	ulonglong m_nTransferID;
	/** */
	CString sNick;
	/** */
	CString sBuffer;
	/** remote filesize */
	ulonglong m_nFileSize;
	/** start transfer from this fileposition */
	ulonglong m_nStartPosition;
	/** */
	ulonglong m_nEndPosition;
	/** bytes transfered */
	ulonglong m_nTransfered;
	/** wanted bytes */
	ulonglong m_nChunkSize;	
	/** */
	bool m_bListener;
	/** */
	long m_nFileBufferPos;
	/** */
	long m_nFileBufferSize;
	/** */
	ulonglong m_nTransferRate;
	/** */
	eConnectionState eMode;
	/** */
	eltMedium eMedium;
	/** */
	bool m_bIdle;
	/** */
	CFile m_File;
	/** */
	CByteArray * pByteArray;
	/** local filename */
	CString sSrcFilename;
	/** remote filename */
	CString sDstFilename;
	/** local direction */
	eDirection eSrcDirection;
	/** remote direction */
	eDirection eDstDirection;
	/** remote nick */
	CString sDstNick;
	/** local level */
	int m_nSrcLevel;
	/** local level */
	int m_nDstLevel;
	/** identifier hubname */
	CString sHubName;
	/** identifier hubhost:hubport */
	CString sHubHost;
	/** */
	struct timeval starttime;
	/** */
	ulonglong m_nPendingSendBytes;
	/** */
	CThread TransferThread;
	/** callback function */
	_CCallback * pCallback;
	/** */
	eTransferState m_eTransferState;
	/** */
	eTransferType m_eTransferType;
	/** */
	CMessageSupports m_MessageSupports;
	/** */
	CMessageLock m_MessageLock;
	/** */
	struct sAverageTransferRate m_AverageTransferRate;
	/** */
	CZLib m_ZLib;
};

/** */
inline CString CTransfer::GetDstFilename() const
{ return sDstFilename; }
/** */
inline void CTransfer::SetDstFilename( CString filename )
{ TransferThread.Lock(); sDstFilename=filename; TransferThread.UnLock(); }
/** */
inline CString CTransfer::GetSrcFilename() const
{ return sSrcFilename; }
/** */
inline void CTransfer::SetSrcFilename( CString filename )
{ TransferThread.Lock(); sSrcFilename=filename; TransferThread.UnLock(); }
/** */
inline CString CTransfer::GetDstNick() const
{ return sDstNick; }
/** */
inline CString CTransfer::GetHubHost() const
{ return sHubHost; }
/** */
inline void CTransfer::SetHubHost( CString hubhost )
{ TransferThread.Lock(); sHubHost=hubhost; TransferThread.UnLock(); }
/** */
inline CString CTransfer::GetHubName() const
{ return sHubName; }
/** */
inline void CTransfer::SetHubName( CString hubname )
{ TransferThread.Lock(); sHubName=hubname; TransferThread.UnLock(); }
/** */
inline void CTransfer::SetMedium( eltMedium medium )
{ TransferThread.Lock(); eMedium=medium; TransferThread.UnLock(); }
/** */
inline eltMedium CTransfer::GetMedium() const
{ return eMedium; }
/** */
inline eDirection CTransfer::GetSrcDirection() const
{ return eSrcDirection; }
/** */
inline void CTransfer::SetSrcDirection( eDirection direction )
{ TransferThread.Lock(); eSrcDirection = direction; TransferThread.UnLock(); }
/** */
inline eDirection CTransfer::GetDstDirection() const
{ return eDstDirection; }
/** */
inline void CTransfer::SetDstDirection( eDirection direction )
{ TransferThread.Lock(); eDstDirection = direction; TransferThread.UnLock(); }
/** */
inline int CTransfer::GetSrcLevel() const
{ return m_nSrcLevel; }
/** */
inline int CTransfer::GetDstLevel() const
{ return m_nDstLevel; }
/** */
inline eConnectionState CTransfer::GetMode() const
{ return eMode; }
/** */
inline void CTransfer::SetMode( eConnectionState mode )
{ TransferThread.Lock(); eMode = mode; TransferThread.UnLock(); }
/** */
inline ulonglong CTransfer::GetStartPosition() const
{ return m_nStartPosition; }
/** */
inline void CTransfer::SetStartPosition( ulonglong pos )
{ TransferThread.Lock(); m_nStartPosition=pos; TransferThread.UnLock(); }
/** */
inline ulonglong CTransfer::GetEndPosition() const
{ return m_nEndPosition; }
/** */
inline void CTransfer::SetEndPosition( ulonglong pos )
{ TransferThread.Lock(); m_nEndPosition=pos; TransferThread.UnLock(); }
/** */
inline ulonglong CTransfer::GetLength() const
{ return m_nFileSize; }
/** */
inline void CTransfer::SetLength( ulonglong length )
{ TransferThread.Lock(); m_nFileSize = length; TransferThread.UnLock(); }
/** */
inline ulonglong CTransfer::GetTransfered() const
{ return m_nTransfered; }
/** */
inline void CTransfer::SetNick(CString nick)
{ TransferThread.Lock(); sNick=nick; TransferThread.UnLock(); }
/** */
inline CString CTransfer::GetNick()
{ return sNick; }
/** */
inline void CTransfer::SetRate( ulonglong rate )
{ TransferThread.Lock(); m_nTransferRate=rate; TransferThread.UnLock(); }
/** */
inline ulonglong CTransfer::GetRate() const
{ return m_nTransferRate; }
/** */
inline bool CTransfer::IsIdle() const
{ return m_bIdle; }
/** */
inline void CTransfer::SetCallBackFunction( _CCallback * callback )
{ TransferThread.Lock(); if ( pCallback ) delete pCallback; pCallback = callback; TransferThread.UnLock(); }
/** */
inline void CTransfer::SetDone( eTransferState e )
{ TransferThread.Lock(); m_eTransferState = e; TransferThread.UnLock(); }
/** */
inline eTransferState CTransfer::GetDone() const
{ return m_eTransferState; }
/** */
inline time_t CTransfer::GetStartTime() const
{ return starttime.tv_sec; }
/** */
inline void CTransfer::SetStartTime( time_t t )
{ TransferThread.Lock(); starttime.tv_sec = t; TransferThread.UnLock(); }
/** */
inline ulonglong CTransfer::GetTransferID() const
{ return m_nTransferID; }
/** */
inline void CTransfer::SetTransferID( ulonglong transferid )
{ TransferThread.Lock(); m_nTransferID = transferid; TransferThread.UnLock(); }
/** */
inline eTransferType CTransfer::GetTransferType() const
{ return m_eTransferType; }
/** */
inline void CTransfer::SetTransferType( eTransferType type )
{ TransferThread.Lock(); m_eTransferType = type; TransferThread.UnLock(); }

#endif
