/*! \file picloudserver.h
 * \brief PICloud Server
*/
/*
	PIP - Platform Independent Primitives
	PICloud Server
	Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@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 PICLOUDSERVER_H
#define PICLOUDSERVER_H

#include "picloudbase.h"
#include "piconditionvar.h"


class PIP_CLOUD_EXPORT PICloudServer : public PIIODevice, private PICloudBase
{
	PIIODEVICE(PICloudServer)
public:
	//!
	explicit PICloudServer(const PIString & path = PIString(), PIIODevice::DeviceMode mode = PIIODevice::ReadWrite);
	virtual ~PICloudServer();

	class Client : public PIIODevice {
		PIIODEVICE(PICloudServer::Client)
		friend class PICloudServer;
	public:
		Client(PICloudServer * srv = nullptr, uint id = 0);
		virtual ~Client();
	protected:
		bool openDevice();
		bool closeDevice();
		int readDevice(void * read_to, int max_size);
		int writeDevice(const void * data, int size);
		DeviceInfoFlags deviceInfoFlags() const {return PIIODevice::Reliable;}

	private:
		void pushBuffer(const PIByteArray & ba);
		PICloudServer * server;
		uint client_id;
		PIByteArray buff;
		PIMutex mutex_buff;
		PIConditionVariable cond_buff;
		std::atomic_bool is_connected;
	};

	void setServerName(const PIString & server_name);

	PIVector<PICloudServer::Client *> clients() const;

	EVENT1(newConnection, PICloudServer::Client * , client)

protected:
	bool openDevice();
	bool closeDevice();
	int readDevice(void * read_to, int max_size);
	int writeDevice(const void * data, int max_size);

private:
	EVENT_HANDLER1(void, _readed, PIByteArray &, ba);
	EVENT_HANDLER1(void, clientDeleted, PIObject *, o);
	void clientDisconnect(uint client_id);
	int sendData(const PIByteArray & data, uint client_id);

	PIVector<Client *> clients_;
	PIMap<uint, Client *> index_clients;
	mutable PIMutex clients_mutex;
};

#endif // PICLOUDSERVER_H
