# -*- encoding: utf-8 -*-

import os
import json, requests

from logger import *

class TaskManager(object):
	"""Class for communication with service engine. Has functions for retrieving new task (if available)
		and finishing completed tasks."""
	def __init__(self, config, logger):
		"""Constructor
			config - config given in the form of dictionary containing required paths and request data.
			logger - logger instance (as in logger.py)
		"""
		self.logger = logger
		self.process_dir = config['process_dir']
		self.done_dir = config['done_dir']
		self.tasker_url = config['tasker_url']
		self.request_headers = config['request_headers']
		self.data = config['data']

	def get_new_task(self):
		"""Retrieves new task from the queue if available. Engine is responsible for moving task to processing.
			returns: pair of path to task file and task options. If no task is available at the moment
					returns pair of Nones
		"""
		try:
			self.logger.log(DEBUG, "Sending POST request to the tasker")
			response_txt = requests.post(self.tasker_url, data=json.dumps(self.data), headers=self.request_headers)
			response = json.loads(response_txt.text)

			task_file = None
			task_options = None
			if 'task' in response and response['task']:
				self.logger.log(DEBUG, "Getting data out of response")
				task_token = response['task'].encode('ascii', 'ignore')
				task_file = os.path.join(self.process_dir, task_token)
				task_options = json.loads(response['options'].encode('ascii', 'ignore'))
			elif 'task' not in response:
				self.logger.log(DEBUG, "No `task` key in response")
				self.logger.log(DEBUG, "response: " + response_txt.text)
			elif not response['task']:
				self.logger.log(DEBUG, "No new tasks available")
			return task_file, task_options
		except Exception as e:
			self.logger.log(ERROR, "Unable to fetch task")
			self.logger.log(ERROR, e)

	def finish_task(self, task_token):
		"""Finishes task with given path - checks for corresponding file in done and removes
			task file from processing.
			task_token can also be a path to any of task files (queued, progress or done)."""
		task_token = self.get_task_token(task_token)	# in case we provided path instead of token
		done_path = self.get_task_done_path(task_token)
		process_path = os.path.join(self.process_dir, task_token)
		if not os.path.exists(done_path):
			self.logger.task_log(task_token, ERROR, "Task finished, but no result file in done dir!")
		else:
			self.logger.log(DEBUG, "Finishing task " + task_token)
			try:
				os.remove(process_path)
			except Exception as e:
				self.logger.log(ERROR, "Unable to finish task " + task_token)
				self.logger.log(ERROR, e)
			else:
				self.logger.log(INFO, "Finished task: " + task_token)

	def get_task_token(self, task_path):
		"""Returns task token from path (it cen be queue, processing or done path)"""
		return os.path.basename(task_path)

	def get_task_done_path(self, task_token):
		"""Returns task done path from it's queue or progess path.
			task_token can also be a path to any of task files (queued, progress or done)."""
		task_token = self.get_task_token(task_token)	# in case we provided path instead of token
		task_done_path = os.path.join(self.done_dir, task_token)
		return task_done_path
