/* -----------------------------------------------------------------------------
	GSFramework
	Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */


#ifndef	__NIONETSERVER__
#define	__NIONETSERVER__


		#include "network_enet/enet_network.h"
		#include "filesystem/io_handle.h"
		#include "memory/nauto_ptr.h"
		#include "container/nlist.h"
		#include "nstring/nstring.h"
		#include "time/ntime.h"


namespace GS {
	namespace NML { class File; }
	namespace IO {

//
template <typename T> struct Measure
{
		Time		time;
		T			value;
};

/*!
	@short	Networked I/O server.
	@author	Emmanuel Julien (ejulien@nworks.fr)
*/
class	NetServer : public Network::Enet
{
		SharedPtr <Base> basefs;	// Support IO system.

		Measure <int> bandwidth_measure;
		int			bandwidth;

// Client handle info
struct	ClientHandleInfo
{
		int			id;
		String		name;

		AutoPtr <Handle> handle;

		ClientHandleInfo() : id(0) {}
};

// Connected peer
struct	Client
{
		void		*peer;
		int			handshake_step;

		AutoList <ClientHandleInfo *> handles;

		Client(void *p) : peer(p), handshake_step(0) {}
};

		AutoList <Client *> clients;

		bool		ProcessOpenCommand(Client &, StringList &);
		bool		ProcessReadCommand(Client &, StringList &);
		bool		ProcessSeekCommand(Client &, StringList &);
		bool		ProcessTellCommand(Client &, StringList &);
		bool		ProcessCloseCommand(Client &, StringList &);
		bool		ProcessHashCommand(Client &, StringList &);
		bool		ProcessClientRequest(Client &, const String &);

		int			GetClientOpenHandleCount(const Client &) const;
		int			GetClientFreeHandleIndex(const Client &) const;
		Handle		*GetClientHandle(const Client &, int handle_id) const;
		Client		*GetClient(void *peer);

public:

struct	Statistics
{
		bool		connected;

		int			sent_data;		// in bytes
		int			bandwidth;		// in bytes

		int			packet_loss;	// in %

	struct	Handle
	{
		String		name;
	};

		Array <Handle> handles;

		Statistics() : connected(false), sent_data(0), bandwidth(0), packet_loss(0) {}
};

		void		GetStatistics(Statistics &);

		const AutoList <Client *> &GetClients() const { return clients; }

virtual	void		OnPeerConnection(void *peer);
virtual	void		OnPacketReceived(void *peer, const void *, size_t);
virtual	void		OnConnectionClosed(void *peer);

		bool		Start(const char *ip, int port);
		void		Stop();

		NetServer(Base *);
		~NetServer();
};

	} // IONet
} // GS


#endif	// __NIONETSERVER__
