#pragma once

#include "NetChannel.h"

namespace ehs
{
	class NetEnd;

	class NetServerCh : public NetChannel
	{
	private:
		friend class EHC;

		Vector<NetEnd *> endpoints;
		UInt_64 maxEndpoints;

	public:
		~NetServerCh() override;

		NetServerCh();

		NetServerCh(Str_8 name, const Version &version, UInt_64 maxEndpoints);

		NetServerCh(NetServerCh &&server) noexcept;

		NetServerCh(const NetServerCh &server);

		NetServerCh &operator=(NetServerCh &&server) noexcept;

		NetServerCh &operator=(const NetServerCh &server);

		virtual bool OnEndpointConnect(NetEnd *endpoint, Serializer<UInt_64> payload);

		virtual Serializer<UInt_64> OnEndpointAccepted(NetEnd *endpoint);

		virtual void OnEndpointDisconnect(NetEnd *endpoint, Serializer<UInt_64> payload);

		virtual void OnEndpointTimeout(NetEnd *endpoint);

		virtual void OnEndpointActive(NetEnd *endpoint);

		virtual Serializer<UInt_64> OnShutdown();

		void Broadcast(NetStatus endStatus, bool deltaLocked, UInt_64 encHashId,
					   bool ensure, UInt_64 sysHashId, UInt_64 opHashId,
					   const Serializer<UInt_64> &payload);

		void Broadcast(NetStatus endStatus, bool deltaLocked, const Str_8 &encId,
					   bool ensure, const Str_8 &sysId, const Str_8 &opId,
					   const Serializer<UInt_64> &payload);

		bool HasEndpoint(NetStatus endStatus, const Char_8 token[64]) const;

		bool HasEndpoint(NetStatus endStatus, UInt_64 hashId) const;

		bool HasEndpoint(NetStatus endStatus, const Str_8 &id) const;

		bool HasEndpoint(const Char_8 token[64]) const;

		bool HasEndpoint(UInt_64 hashId) const;

		bool HasEndpoint(const Str_8 &id) const;

		bool HasEndpoint(const Endpoint &endpoint) const;

		NetEnd *GetEndpoint(NetStatus endStatus, const Char_8 token[64]) const;

		NetEnd *GetEndpoint(NetStatus endStatus, UInt_64 hashId) const;

		NetEnd *GetEndpoint(NetStatus endStatus, const Str_8 &id) const;

		NetEnd *GetEndpoint(const Char_8 token[64]) const;

		NetEnd *GetEndpoint(UInt_64 hashId) const;

		NetEnd *GetEndpoint(const Str_8 &id) const;

		NetEnd *GetEndpoint(const Endpoint &endpoint) const;

		Array<NetEnd *> GetEndpoints(NetStatus endStatus);

		UInt_64 GetEndpointsCount(NetStatus endStatus);

		UInt_64 GetMaxEndpoints() const;

	private:
		void Process(const float &delta, const Endpoint &endpoint, const Header &header, Serializer<UInt_64> &payload) override;

		void GenerateToken(Char_8 in[64]);

		void UpdateQueue(UInt_64 active);

		void UpdateQueue();

		bool RemoveEndpoint(const Char_8 token[64]);

		bool RemoveEndpoint(const Endpoint &endpoint);

		bool RemoveEndpoint(const NetEnd* end);

		void Poll(const float &delta) override;

		void Shutdown();
	};
}