#ifndef sServer_h
#define sServer_h
#include "sSocket.h"
#include "misc.h"
#ifdef DIPL_LOG
#include "CentralLog.h"
#endif

class sSocket;
typedef enum {
	NEU		 =  1,
	NOT_LOGIN	 =  2,
	INVALID_ID	 =  3,
	SEND_FILE_LIST	 =  4,
	REQUEST_NEXT_200 =  5,
	REQ_SERVER	 =  6,
	UNUSED_SERVER	 =  7,
	ID_CHANGED	 =  8,
	SEARCH		 =  9,
	READY_SERVER	 = 10,
	SERVER_CLOSED	 = 11,
	WAIT_SERVER_LIST = 12,
	WAIT_SOURCES	 = 13,
	SEARCH_USER	 = 14,
	SEARCH_FILE	 = 15,
	WAIT_LOGIN	 = 16,
	WAIT_REQUEST	=  17,
	TIMEOUT			= 18 
	} eServer_status;

#define SERVER_LIST	for (sServer *akt = sServer::first_Server; akt != NULL; akt = akt->next_Server)

/// cDonkey server part: each instance of this class handles a client->server connection 
class sServer:public sSocket {
	public:
static	unsigned int	 count;			// total number of current Sources (MFTP)
static  class sServer	*first_Server; 
	class sServer	*next_Server;
	private:
	char 		*last_file;
	void		 initList (void);
	eServer_status	 status;
	int		 last_code;
	time_t		 next_search;

	// (TM)
	class ClientLogClass *SelfLog;                                   ///< Object which takes care of traffic counting. 
	tHash            the_others_hash;                                ///< Stores the other's client hash value.
	char            *the_others_name;                                ///< Stores the user name internally.
	unsigned int     the_others_version;                             ///< Stores the other's client version number.
	int              the_others_listening_port;                      ///< Stores the port the other listens on for connections.

	int		 REQ_server_info	(class sPacket *packet); // (0x01)
	int		 RES_unwanted		(class sPacket *packet); // (0x05) (log.info)
	int		 REQ_serverList		(class sPacket *packet); // (0x14) (log.info)
	int		 RES_offerFiles		(class sPacket *packet); // (0x15)
	int		 REQ_file_search	(class sPacket *packet); // (0x16)
	int		 REQ_sources		(class sPacket *packet); // (0x19)
	int		 RES_server_list	(class sPacket *packet); // (0x32) (log.info)
	int		 RES_search		(class sPacket *packet); // (0x33)
	int		 RES_online_stat	(class sPacket *packet); // (0x34) (log.statistik)
	int		 RES_connect_req	(class sPacket *packet); // (0x35) Solte in warteschleife
	int		 RES_server_message	(class sPacket *packet); // (0x38) (log.info) KEINE STATUS ÄNDERUNG
	int		 RES_change_id		(class sPacket *packet); // (0x40)
	int		 RES_version		(class sPacket *packet); // (0x41) KEINE STATUS ÄNDERUNG
	int		 RES_sources		(class sPacket *packet); // (0x42) wird in die auptschleife verschoen (sSource)
	int		 RES_search_user	(class sPacket *packet); // (0x43) Erzeugt neues sfile Object !!!
	public:
	unsigned int	 my_id;

	// (TM)
	int		 GetUserVersion();                               ///< Returns the client's version.
	void             GetUserHash(tHash *);                           ///< Copies hash into the variable given by pointer.
	char            *GetUserName();                                  ///< Just returns the pointer the_others_name.
	int              GetUserListeningPort();                         ///< Returns the port on which the other 
                                                                         ///< listens for incoming connections

	int		 CMD_client_info_server	(void              ); // (0x01)
//	int		 CMD_bad_version	(void		   ); // (0x05)	
	int		 CMD_req_server_list	(void              ); // (0x14)
	int		 CMD_files_offer	(void              ); // (0x15)
	int		 CMD_search4gui		(const class sGui *gui   ); // (0x16)
	int		 CMD_suche_filename	(const char *name  ); // (0x16)
//	int		 CMD_disconnect		(void		   ); // (0x18) Disconnect send it the client or the server ?
	int		 CMD_suche_download	(const tHash &hash ); // (0x19)
	int		 CMD_suche_user		(const char *name  ); // (0x1A) unused currently
	int		 CMD_get_client_info	(uint32_t idx      ); // (0x1C) unused currently
// {{{ depricated	
//	int		 CMD_query_chats	(		   ); // (0x1D) depricated
//	int		 CMD_chat_message	(		   ); // (0x1D) depricated
//	int		 CMD_join_room		(		   ); // (0x1D) depricated
// }}}
	int		 CMD_req_next_200	(void              ); // (0x21)
	int		 res_server_list	(void              ); // (0x32) (log.info)
//	int		 CMD_search_result	(		   ); // (0x33) direct send after search maybe changed later	
//	int		 CMD_server_status	(		   ); // (0x34) if not send safe bandwith (maybe not needed)
	int  		 CMD_callback		(in_addr ip, uint16_t port); // (0x35)
	int  		 CMD_callback_failed	(void              ); // (0x36)
//	int		 CMD_message		(const char *text  ); // (0x38) TODO
// depricated {{{	
//	int		 CMD_room_request	(		   ); // (0x39) depricated
//	int		 CMD_broadcast		(		   ); // (0x3A) depricated
//	int		 CMD_user_join		(		   ); // (0x3B) depricated
//	int		 CMD_user_leave		(		   ); // (0x3C) depricated
//	int		 CMD_user		(		   ); // (0x3D) depricated
// }}}	
	int		 res_change_id		(void              ); // (0x40)
//	int		 CMD_server_version	(		   ); // (0x41) if not send safe bandwith (maybe not needed)
	int		 CMD_res_sources	(const tHash &hash ); // (0x42)
//	int		 CMD_user_list		(		   ); // (0x43) direct send after search maybe changed later
	void		 readWork(void);
	int  		 Donkey_server (sPacket *packet);
	void		 Code	 (int i) { last_code = i; }
static  unsigned int	 to_me;
	bool		 isServer;
	char		 padding1;
	char		 padding2;
	char		 padding3;
			 sServer (class cSocket *FD, struct in_addr, uint16_t PORT);
			 sServer (in_addr ip, unsigned short port);
virtual			~sServer ();
	bool		 searchFile (const char *name);
	unsigned int   	 getID   (void) const;
	int		 Status	 (void) const { return status; }
	void		 Status	 (eServer_status i) { status = i; };
	class sFile	*forFile (void) const;
	void		 forFile (class sFile *);
virtual	void		 Work	 (void);
	void	       	 setID	 (unsigned int id);
const	char 		*lastFile(void ) const;
	const char *Statusname (void);
	};

int Donkey_server (sServer *server, sPacket *packet);
// vim:fdm=marker
#endif
