//! \~\file piclientserver_server.h
//! \~\ingroup ClientServer
//! \brief
//! \~english TCP Server
//! \~russian TCP Сервер
/*
    PIP - Platform Independent Primitives
    Ivan Pelipenko peri4ko@yandex.ru

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef piclientserver_server_H
#define piclientserver_server_H

#include "pimutex.h"
#include "pinetworkaddress.h"
#include "pip_client_server_export.h"
#include "pistreampacker.h"
#include "pithreadnotifier.h"

class PIEthernet;
class PIThread;

namespace PIClientServer {

class ServerClient;

//! \~\ingroup ClientServer
//! \~\brief
//! \~english TCP server implementation for client-server communication. Accepts incoming connections and manages multiple clients with
//! configurable factory for client instance creation.
//! \~russian Реализация TCP сервера для клиент-серверного взаимодействия. Принимает входящие соединения и управляет несколькими клиентами с
//! настраиваемой фабрикой для создания экземпляров клиентов.
class PIP_CLIENT_SERVER_EXPORT Server: public PIStreamPackerConfig {
	friend class ServerClient;
	NO_COPY_CLASS(Server);

public:
	//! \~english Constructs a stopped server with default limits.
	//! \~russian Создает остановленный сервер с ограничениями по умолчанию.
	Server();

	//! \~english Stops the server and releases transport resources.
	//! \~russian Останавливает сервер и освобождает транспортные ресурсы.
	virtual ~Server();

	//! \~english Starts listening for clients on address "addr".
	//! \~russian Начинает принимать клиентов по адресу "addr".
	void listen(PINetworkAddress addr);

	//! \~english Starts listening on all interfaces at port "port".
	//! \~russian Начинает прослушивание на всех интерфейсах на порту "port".
	//! \~\details
	//! \~english Equivalent to listen({0, port}), binds to all available network interfaces.
	//! \~russian Эквивалентно listen({0, port}), привязывается ко всем доступным сетевым интерфейсам.
	void listenAll(ushort port) { listen({0, port}); }


	//! \~english Stops accepting clients and shuts the server down.
	//! \~russian Прекращает прием клиентов и завершает работу сервера.
	void stopServer();

	//! \~english Closes all currently connected clients.
	//! \~russian Закрывает все текущие клиентские соединения.
	//! \~\details
	//! \~english Immediately closes all active client connections without stopping the server.
	//! \~russian Немедленно закрывает все активные клиентские соединения без остановки сервера.
	void closeAll();


	//! \~english Returns the configured maximum number of simultaneous clients.
	//! \~russian Возвращает настроенный максимум одновременных клиентов.
	int getMaxClients() const { return max_clients; }

	//! \~english Sets the maximum number of simultaneous clients.
	//! \~russian Устанавливает максимальное число одновременных клиентов.
	//! \~\details
	//! \~english Sets the maximum number of concurrent client connections. Default is 1000.
	//! \~russian Устанавливает максимальное количество одновременных клиентских подключений. По умолчанию 1000.
	void setMaxClients(int new_max_clients);

	//! \~english Returns the number of currently connected clients.
	//! \~russian Возвращает текущее количество подключенных клиентов.
	int clientsCount() const;


	//! \~english Calls "func" for each currently connected client.
	//! \~russian Вызывает "func" для каждого текущего подключенного клиента.
	void forEachClient(std::function<void(ServerClient *)> func);


	//! \~english Sets the factory used to create accepted client objects.
	//! \~russian Устанавливает фабрику, создающую объекты принятых клиентов.
	void setClientFactory(std::function<ServerClient *()> f) { client_factory = std::move(f); }

private:
	void newClient(ServerClient * c);
	void clientDisconnected(ServerClient * c);

	std::function<ServerClient *()> client_factory;
	std::atomic_bool is_closing = {false};
	PIEthernet * tcp_server     = nullptr;
	PIThread * clean_thread     = nullptr;
	PIThreadNotifier clean_notifier;
	PIVector<ServerClient *> clients;
	mutable PIMutex clients_mutex;

	int max_clients = 1000;
};

} // namespace PIClientServer

#endif
