#ifndef sSource_h
#define sSource_h
#include "sSocket.h"
#include "misc.h"
#include "cVerify.h"

typedef enum {
	WAIT_INFO 		=  2,
	READY			=  3,
	UNUSED			=  4,
	WAIT_OFFER_FILE		=  5,
	REQ_SLOT		=  6,
	WAIT_SLOT		=  7,
	SEND_HELLO		=  8,
	WAIT_HELLO		=  9,
	e_resInfo		= 11,
	P_C5060			= 12,
	FTP_AKTIVE		= 13,
	FILE_AVAIL		= 14,
	WAIT_PART_DATA		= 15,
	File_select		= 16
	} eSource_status;

#define SOURCE_LIST	for (sSource *akt = sSource::first_Source; akt != NULL; akt = akt->next_Source)

void File_info_open  (void) ;
void File_info_close (void) ;

class sFile;

class sSource : public sSocket {
	public:
	unsigned int	 sort;
static	unsigned int	 count0;		// total number of current Sources (MFTP)
static	unsigned int	 count1;		// total number of current Sources (MFTP)
static	unsigned int	 count;			// total number of current Sources (MFTP)
static  class sSource	*first_Source;
	class sSource	*next_Source;
	long		 ratio;
	char 		*name;
	int		 dl_slot;
	tRange_Map	*avail;			// List of Blocks that are available from this source
	size_t		 part_len;		// used bytes of part_ok (will become deprecated)
	char		 part_ok[64];		// This is ok up to 4GB (will be replaced by avail)
private:uint8_t		 peer_hash[16];
	bool		 ftp_aktive;
	time_t		 next_slot;
	time_t		 ul_next_event;
	time_t		 dl_next_event;
	unsigned int 	 version;
	int		 last_code;
	int		 extra_status;
	z_stream	*zip;
public:	eSource_status	 status;
	uint8_t		 ul_hash[16];
	uint8_t		 dl_hash[16];
	class sFile	 *dl_file;
private:size_t		 dl_von[3], dl_bis[3];
	uint32_t	 ul_von[3], ul_bis[3];
	int		 ul_rang;
	int		 dl_rang;
	bool		 have_slot;
	bool		 ask_sources;
	bool		 dl_select;
	bool		 eMule;
	bool		 overnet;
	bool		 compress;
	bool		 recvData;
	bool		 ask_info;
	bool		 auto_select;
	bool	 	 logged ; 		// is the download/uploader already displayed
public:
	uint16_t	 client_udp;	// eMule protocol
private:
	void		 Init(void);
	void		 moreData_recv       (uint32_t  von, uint32_t  bis);
	bool		 calcUpload_block    (size_t   &von, size_t   &bis);
// {{{ Packet empfang
	int		 REQ_client_info      (sPacket *packet); // (0x01)
	int		 C5_client_info       (sPacket *packet); // (0x01/0x02)
	int		 C5_compressed_data   (sPacket *packet); // (0x40)
	int		 RES_part_data        (sPacket *packet); // (0x46)
	int		 REQ_part_data        (sPacket *packet); // (0x47)
	int		 RES_no_such_file     (sPacket *packet); // (0x48)
	int		 RES_dl_ende          (sPacket *packet); // (0x49)
	int		 RES_shared_files     (sPacket *packet); // (0x4B)
	int		 REQ_shared_files     (sPacket *packet); // (0x4A)
	int		 RES_client_login     (sPacket *packet); // (0x4C)
	int		 RES_changed_server   (sPacket *packet); // (0x4D)
	int		 RES_source_message   (sPacket *packet); // (0x4E) (log.info)
	int 		 REQ_status           (sPacket *packet); // (0x4F)
	int 		 RES_status           (sPacket *packet); // (0x50) Return file Status
	int 		 REQ_part_hash        (sPacket *packet); // (0x51)
	int 		 RES_part_hash        (sPacket *packet); // (0x52) Return partial hashes
	int 		 REQ_slot             (sPacket *packet); // (0x54)
	int 		 RES_slot_avail       (sPacket *packet); // (0x55)
	int 		 RES_slot_release     (sPacket *packet); // (0x56)
	int 		 RES_slot_close       (sPacket *packet); // (0x57)
	int 		 REQ_fileName 	      (sPacket *packet); // (0x58)
	int 		 RES_fileName         (sPacket *packet); // (0x59)
	int 		 RES_5b_unknown       (sPacket *packet); // (0x5B)
	int 		 RES_5c_unknown       (sPacket *packet); // (0x5C)
	int		 C5_res_rang          (sPacket *packet); // (0x60)
	int		 C5_rating 	      (sPacket *packet); // (0x61)
	int		 C5_req_sources       (sPacket *packet); // (0x81)
	int		 D4_res_sources       (sPacket *packet); // (0x82) Currently unused
	int		 C5_res_sources       (sPacket *packet); // (0x82)
// }}}
// Packet senden {{{
	int		 client_info	      (uint8_t opcode    ); // (0x01/0x4C)
	int		 C5_client_info       (bool first        ); // (0x01/0x02)
	int		 res_part_data        (void              ); // (0x46)
	int		 req_part_data	      (void		 ); // (0x47)
	int		 no_such_file         (const tHash &hash ); // (0x48)
	int		 end_of_download      (void		 ); // (0x49)
	int 		 CMD_req_shared_list  (void              ); // (0x4A) Currently unused
	int 		 res_shared_files     (void              ); // (0x4B) Currently unused (maybe never again used)
	int 		 CMD_client_message   (const char *msg   ); // (0x4E) Currently unused
	int 		 req_file_status      (const tHash &hash ); // (0x4F)
	int		 res_part_status      (tHash &hash       ); // (0x50)
	int 		 req_part_hash        (const tHash &hash ); // (0x51)
	int 		 res_part_hash        (void		 ); // (0x52)
	int  		 req_slot             (void		 ); // (0x54)
	int  		 CMD_slot_available   (void		 ); // (0x55)
	int  		 res_slot_close       (void	 	 ); // (0x57)
	int  		 req_fileName         (const tHash &hash ); // (0x58)
	int		 res_offer_file       (const class sFile *file ); // (0x59)
	int		 C5_req_sources       (const tHash &hash ); // (0x81)
	int  		 C5_res_rang          (uint8_t rang      ); // (0x60)
// }}}
	int		 Donkey_client  	(sPacket *packet);
	int		 Donkey_emule   	(sPacket *packet);
	int		 Donkey_emule_packed  	(sPacket *packet);

	void		 setPartOK	(const unsigned char *a, size_t len);
	void		 ulFile 	(const tHash &hash);
	void 		 Name 		(const char *name);
	void		 extraSend	(int i     ) 		{ extra_status = i; }
	void		 Code		(int i     ) 		{ last_code = i; }
	void		 Compress	(bool c    ) 		{ compress = c; }
	bool		 PartInfo	(void) const { return part_len > 0; }
	public: // Later private again
	// Used by sGui
	bool		 haveSlot 	(void) const { return have_slot	; }
	int		   dlSlot 	(void) const { return dl_slot	; }
	long		 Ratio		(void) const { return ratio ; }
	bool		 is_eMule	(void) const { return eMule ; }
	bool		 is_Overnet	(void) const { return overnet ; }
	// used in main loop
	eSource_status	 Status		(void) const { return status	; }
	void		 readWork	(void);
virtual	void		 Work		(void );
	void		 dlFile 	(const tHash &hash);
	class	sFile	*ulFile 	(void);
			 sSource 	(struct in_addr Ip, uint16_t PORT);
			 sSource 	(class cSocket *fd);
virtual			~sSource	();
	bool		 partStatus	(uint32_t i) const;
	};


bool File_info_get   (const uint8_t *peer_hash, const uint8_t *file_hash, size_t file_size, uint8_t *file_info);
void File_info_del   (const uint8_t *peer_hash, const uint8_t *file_hash);



// vim:fdm=marker
#endif
