# Copyright (C) 2015-2016 Red Hat, Inc. All rights reserved.
#
# This copyrighted material is made available to anyone wishing to use,
# modify, copy, or redistribute it subject to the terms and conditions
# of the GNU General Public License v.2.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

import threading
# noinspection PyUnresolvedReferences
from gi.repository import GLib
from .job import Job
from . import cfg
import traceback
from .utils import log_error


class RequestEntry(object):
	def __init__(self, tmo, method, arguments, cb, cb_error,
			return_tuple=True, job_state=None):
		self.tmo = tmo
		self.method = method
		self.arguments = arguments
		self.cb = cb
		self.cb_error = cb_error

		self.timer_id = -1
		self.lock = threading.RLock()
		self.done = False
		self._result = None
		self._job = None
		self._rc = 0
		self._rc_error = None
		self._return_tuple = return_tuple
		self._job_state = job_state

		if self.tmo < 0:
			# Client is willing to block forever
			pass
		elif tmo == 0:
			self._return_job()
		else:
			self.timer_id = GLib.timeout_add_seconds(
				tmo, RequestEntry._request_timeout, self)

	@staticmethod
	def _request_timeout(r):
		"""
		Method which gets called when the timer runs out!
		:param r:  RequestEntry which timed out
		:return: Nothing
		"""
		r.timer_expired()

	def _return_job(self):
		self._job = Job(self, self._job_state)
		cfg.om.register_object(self._job, True)
		if self._return_tuple:
			self.cb(('/', self._job.dbus_object_path()))
		else:
			self.cb(self._job.dbus_object_path())

	def run_cmd(self):
		try:
			result = self.method(*self.arguments)
			self.register_result(result)
		except Exception as e:
			# Use the request entry to return the result as the client may
			# have gotten a job by the time we hit an error
			# Lets get the stacktrace and set that to the error message
			st = traceback.format_exc()
			cfg.blackbox.dump()
			log_error("Exception returned to client: \n%s" % st)
			self.register_error(-1, str(e), e)

	def is_done(self):
		with self.lock:
			rc = self.done
		return rc

	def get_errors(self):
		with self.lock:
			return (self._rc, self._rc_error)

	def result(self):
		with self.lock:
			if self.done:
				return self._result
			return '/'

	def _reg_ending(self, result, error_rc=0, error_msg=None,
					error_exception=None):
		with self.lock:
			self.done = True
			if self.timer_id != -1:
				# Try to prevent the timer from firing
				GLib.source_remove(self.timer_id)

			self._result = result
			self._rc = error_rc
			self._rc_error = error_msg

			if not self._job:
				# We finished and there is no job, so return result or error
				# now!
				# Note: If we don't have a valid cb or cbe, this indicates a
				# request that doesn't need a response as we already returned
				# one before the request was processed.
				if error_rc == 0:
					if self.cb:
						if self._return_tuple:
							self.cb((result, '/'))
						else:
							self.cb(result)
				else:
					if self.cb_error:
						if not error_exception:
							if not error_msg:
								error_exception = Exception(
									"An error occurred, but no reason was "
									"given, see service logs!")
							else:
								error_exception = Exception(error_msg)

						self.cb_error(error_exception)
			else:
				# We have a job and it's complete, indicate that it's done.
				# TODO: We need to signal the job is done too.
				self._job.Complete = True
				self._job = None

	def register_error(self, error_rc, error_message, error_exception):
		self._reg_ending(None, error_rc, error_message, error_exception)

	def register_result(self, result):
		self._reg_ending(result)

	def timer_expired(self):
		with self.lock:
			# Set the timer back to -1 as we will get a warning if we try
			# to remove a timer that doesn't exist
			self.timer_id = -1
			if not self.done:
				# Create dbus job object and return path to caller
				self._return_job()
			else:
				# The job is done, we have nothing to do
				pass

		return False
