/*******************************************************
 * 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     Job class.
 *  \details   Contains job description data. For each task received by backend, a Job is assigned.
 *  \author    vadims
 *  \date      Nov 26, 2019
 *  \copyright CENOS LLC
 */


#ifndef JOB_HPP_
#define JOB_HPP_

#include <websocketpp/config/asio_no_tls_client.hpp>
#include <string>
#include <queue>
#include <optional>

#include "easylogging++/easylogging++.h"
#include "misc/Timer.hpp"
#include "nlohmann/json.hpp"
#include "PluginManager.h"
#include "misc/Stopper.hpp"

using json = nlohmann::json;

class Job
{

public:

	/// @brief Constructor
	/// @param input - json input (string)
	/// @param hdl - connection handler
	Job(std::string, websocketpp::connection_hdl);

	/// @brief Copy constructor
	Job(const Job&);

	/// @brief Destructor
	~Job();

	/// @brief Assignement operator
	void operator=(const Job&);

	/// @brief function to access argument of job (arg1, arg2, ...)
	/// @param i - index of argument
	std::optional<json> getArg(std::string) const;

	/// @brief accessor to connection handler (hdl_)
	websocketpp::connection_hdl hdl();

	/// @brief accessor to job timer (t_)
	Timer t() const;

	/// @brief accessor to job command (command_)
	std::string command() const;

	/// @brief accessor to job identifier (guid_)
	std::string guid() const;

	/// @brief accessor to job module (module_)
	std::string module() const;

	/// @brief accessor to job port (port_)
	int port() const;

	enum State {
		QUEUED,
		RUNNING,
		STOP_REQUESTED,
		FINISHED
	};

	void changeStateToRunning();

	void changeStateToFinished();

	void changeStateToStopRequested();

	bool isFinished();

	bool isStopRequested();

	Stopper getStopper();

	static std::string getCommandFromInput(std::string) throw();

	void addSubJob(std::shared_ptr<Job> j);

	std::vector< std::shared_ptr<Job>> getSubJobs();

private:

	/// @brief reads arguments from inputJson_ into arg_ vector
	void readArguments();

	/// @brief writes job config (contents of inpJson_) to file named %guid.json
	void writeJobConfig();

	std::string configFileName_;

	/// @brief input json (in constructor received text data is converted to json format)
	json inpJson_;

	/// @brief timer used for timing the execution time for this job. When job is destructed, the timer data are written to log.
	Timer t_;

	/// @brief handler to connection. Used to send data to gui
	websocketpp::connection_hdl hdl_;

	/// @brief command to execute
	std::string command_;

	/// @brief module which this job is assigned to
	std::string module_;

	/// @brief unique guid of the job
	std::string guid_;

	/// @brief port where websocket is connected
	int port_;

	/// @brief arguments passed for this job
	std::map<std::string, json> arg_;

	/// @brief state of this job
	State jobState;

	/// <summary>
	/// Used to pass down to worker stopping information
	/// </summary>
	Stopper stopper;

	/// <summary>
	/// used to check if waiting is needed before sending answer from main job
	/// </summary>
	std::vector<std::shared_ptr<Job>> subjobs;
};


#endif //JOB_HPP_