/*******************************************************
 * Copyright (C) 2017-2020 CENOS Ltd vg@cenos-platform.com
 *
 * This file is part of CENOS.
 *
 * CENOS can not be copied and/or distributed without the express
 * permission of CENOS Ltd
 *******************************************************/
/**
 *  @brief     JobManager class.
 *  @details   JobManager assigns jobs to workers, manages job calls.
 *  @author    vadims
 *  @date      Nov 26, 2019
 *  @copyright CENOS LLC
 */

#ifndef JOBMANAGER_HPP_
#define JOBMANAGER_HPP_

#include <atomic>
#include <deque>
#include <websocketpp/config/asio_no_tls_client.hpp>
#include <websocketpp/client.hpp>
#include "easylogging++/easylogging++.h"
#include "misc/messagedata.hpp"
#include "Job.h"
#include "Worker.h"


class JobManager
{
public:
	/// @brief Constructor of JobManager.
	JobManager();
	~JobManager();

	/** @brief adds job to the jobQueue
	* @param input - json input (string)
	* @param hdl - connection handler
	*/
	void addJob(std::string input, websocketpp::connection_hdl hdl);

	void run();

	/// @brief returns true if JobManager has jobs in jobQueue
	bool hasJobs();

	/// @brief disables sending data to server. Used in tests only
	void disableSending();

	/// @brief prescribes worker for job. 
	/// @description This is actually factory function which returns shared pointer to Worker  
	/// @param job - reference to job, which is used to prescribe worker. Job contains member variable member, which is used to prescribe corresponding worker
	std::shared_ptr<Worker> prescribeWorker(std::shared_ptr<Job>& job, PluginManager m);

	PluginManager getPluginManager() { return pluginManager; }


private:
	std::string input_;
	std::shared_ptr<websocketpp::client<websocketpp::config::asio_client>> client_;
	std::deque<std::shared_ptr<Job>> jobQueue_;
	// running job vector for keeping all currently running jobs. Vital for ability to stop calculation
	std::vector<std::shared_ptr<Job>> runningJobs_;
	std::mutex lck_;
	bool stopAllJobs;
	std::atomic<bool> terminate = false;
	void executeJob(std::shared_ptr<Job>);
	bool sendingEnabled_;
	void send(websocketpp::connection_hdl, std::string);
	PluginManager pluginManager;

};

#endif //JOBMANAGER_HPP_