#ifndef NLP_SERVICE_TASK_MANAGER_H
#define NLP_SERVICE_TASK_MANAGER_H

#include <list>
#include <map>
#include <utility>
#include <boost/filesystem.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/thread/mutex.hpp>

#include <curlpp/Easy.hpp>
#include <json/json.h>

#include "logger.h"

namespace nlp_service {

/* Class responsible for communication with the tasker: getting ne tasks
 * and sending information about finishing work.
 * It uses config file to determine tasker url and method names, as well
 * as tool name and processing and done dirs.
 */
class TaskManager {
public:
	typedef boost::property_tree::ptree task_manager_config;
	typedef std::map<std::string, std::string> task_config;
	typedef std::pair<std::string, task_config> task_description;

	TaskManager(ServiceLoggerPtr logger, task_manager_config& config);
	~TaskManager();

	/* Gets new task from the tasker if one is available. If no task
	 * is available returns empty task_path and logs this fact in main log.
	 */
	task_description get_new_task();

	/* Sends information about finishing task to the tasker and removes task
	 * file from processing dir. If the task failed, because of whatever reason,
	 * the success argument should be set to false.
	 */
	void finish_task(const std::string& task_token, bool success=true);

	/* Gets task token out of task path (no matter the dir: queue, processing,
	 * done or even error). If the token was provided instead of path returns
	 * it unchanged.
	 */
	static std::string get_task_token(const std::string& task_path);

	/* Gets task done path from token or any other path. This is the path
	 * where we want the resulting file to reside.
	 */
	std::string get_task_done_path(const std::string& task_token);

private:
	std::string send_reservation();
	std::string send_response(const std::string& task_token, bool success=true);
	std::string send_data(const std::string& method, const std::map<std::string, std::string>& data);
	task_description parse_reservation_resp(std::string resp);
	void parse_response_resp(std::string resp);
	Json::Value basic_parse_resp(std::string resp, const std::string& check_field);

	template<typename K, typename V>
	static std::string map_to_jsonstr(const std::map<K, V>& dict);
	static task_config json_to_map(Json::Value json_object);

	boost::filesystem::path process_path, done_path;

	std::string tasker_url, get_method, finish_method;
	std::list<std::string> request_headers;
	std::map<std::string, std::string> request_data;

	curlpp::Easy request;
	boost::mutex request_mtx;

	ServiceLoggerPtr logger;
};

typedef boost::shared_ptr<TaskManager> TaskManagerPtr;

}	// end namespace nlp_service

#endif // NLP_SERVICE_TASK_MANAGER_H
