# 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 sys
import threading
import traceback
import dbus
import os
from . import cfg
from .utils import log_debug
from .automatedproperties import AutomatedProperties


# noinspection PyPep8Naming
class ObjectManager(AutomatedProperties):
	"""
	Implements the org.freedesktop.DBus.ObjectManager interface
	"""

	def __init__(self, object_path, interface):
		super(ObjectManager, self).__init__(object_path, interface)
		self.set_interface(interface)
		self._ap_o_path = object_path
		self._objects = {}
		self._id_to_object_path = {}
		self.rlock = threading.RLock()

	@dbus.service.method(
		dbus_interface="org.freedesktop.DBus.ObjectManager",
		out_signature='a{oa{sa{sv}}}')
	def GetManagedObjects(self):
		with self.rlock:
			rc = {}
			try:
				for k, v in list(self._objects.items()):
					path, props = v[0].emit_data()
					rc[path] = props
			except Exception:
				traceback.print_exc(file=sys.stdout)
				sys.exit(1)
			return rc

	def locked(self):
		"""
		If some external code need to run across a number of different
		calls into ObjectManager while blocking others they can use this method
		to lock others out.
		:return:
		"""
		return ObjectManagerLock(self.rlock)

	@dbus.service.signal(
		dbus_interface="org.freedesktop.DBus.ObjectManager",
		signature='oa{sa{sv}}')
	def InterfacesAdded(self, object_path, int_name_prop_dict):
		log_debug(
			('SIGNAL: InterfacesAdded(%s, %s)' %
			(str(object_path), str(int_name_prop_dict))))

	@dbus.service.signal(
		dbus_interface="org.freedesktop.DBus.ObjectManager",
		signature='oas')
	def InterfacesRemoved(self, object_path, interface_list):
		log_debug(('SIGNAL: InterfacesRemoved(%s, %s)' %
			(str(object_path), str(interface_list))))

	def _lookup_add(self, obj, path, lvm_id, uuid):
		"""
		Store information about what we added to the caches so that we
		can remove it cleanly
		:param obj:     The dbus object we are storing
		:param lvm_id:  The user name for the asset
		:param uuid:    The uuid for the asset
		:return:
		"""
		# Note: Only called internally, lock implied

		# We could have a temp entry from the forward creation of a path
		self._lookup_remove(path)

		self._objects[path] = (obj, lvm_id, uuid)
		self._id_to_object_path[lvm_id] = path

		if uuid:
			self._id_to_object_path[uuid] = path

	def _lookup_remove(self, obj_path):
		# Note: Only called internally, lock implied
		if obj_path in self._objects:
			(obj, lvm_id, uuid) = self._objects[obj_path]
			del self._id_to_object_path[lvm_id]
			del self._id_to_object_path[uuid]
			del self._objects[obj_path]

	def lookup_update(self, dbus_obj, new_uuid, new_lvm_id):
		with self.rlock:
			obj_path = dbus_obj.dbus_object_path()
			self._lookup_remove(obj_path)
			self._lookup_add(
				dbus_obj, obj_path,
				new_lvm_id, new_uuid)

	def object_paths_by_type(self, o_type):
		with self.rlock:
			rc = {}

			for k, v in list(self._objects.items()):
				if isinstance(v[0], o_type):
					rc[k] = True
			return rc

	def register_object(self, dbus_object, emit_signal=False):
		"""
		Given a dbus object add it to the collection
		:param dbus_object: Dbus object to register
		:param emit_signal: If true emit a signal for interfaces added
		"""
		with self.rlock:
			path, props = dbus_object.emit_data()

			# print('Registering object path %s for %s' %
			#		(path, dbus_object.lvm_id))

			# We want fast access to the object by a number of different ways
			# so we use multiple hashs with different keys
			self._lookup_add(dbus_object, path, dbus_object.lvm_id,
				dbus_object.Uuid)

			if emit_signal:
				self.InterfacesAdded(path, props)

	def remove_object(self, dbus_object, emit_signal=False):
		"""
		Given a dbus object, remove it from the collection and remove it
		from the dbus framework as well
		:param dbus_object:  Dbus object to remove
		:param emit_signal:  If true emit the interfaces removed signal
		"""
		with self.rlock:
			# Store off the object path and the interface first
			path = dbus_object.dbus_object_path()
			interfaces = dbus_object.interface()

			# print 'UN-Registering object path %s for %s' % \
			#      (path, dbus_object.lvm_id)

			self._lookup_remove(path)

			# Remove from dbus library
			dbus_object.remove_from_connection(cfg.bus, path)

			# Optionally emit a signal
			if emit_signal:
				self.InterfacesRemoved(path, interfaces)

	def get_object_by_path(self, path):
		"""
		Given a dbus path return the object registered for it
		:param path: The dbus path
		:return: The object
		"""
		with self.rlock:
			if path in self._objects:
				return self._objects[path][0]
			return None

	def get_object_by_uuid_lvm_id(self, uuid, lvm_id):
		with self.rlock:
			return self.get_object_by_path(
				self.get_object_path_by_uuid_lvm_id(uuid, lvm_id, None, False))

	def get_object_by_lvm_id(self, lvm_id):
		"""
		Given an lvm identifier, return the object registered for it
		:param lvm_id: The lvm identifier
		"""
		with self.rlock:
			if lvm_id in self._id_to_object_path:
				return self.get_object_by_path(self._id_to_object_path[lvm_id])
			return None

	def get_object_path_by_lvm_id(self, lvm_id):
		"""
		Given an lvm identifier, return the object path for it
		:param lvm_id: The lvm identifier
		:return: Object path or '/' if not found
		"""
		with self.rlock:
			if lvm_id in self._id_to_object_path:
				return self._id_to_object_path[lvm_id]
			return '/'

	def _uuid_verify(self, path, uuid, lvm_id):
		"""
		Ensure uuid is present for a successful lvm_id lookup
		NOTE: Internal call, assumes under object manager lock
		:param path: 		Path to object we looked up
		:param uuid: 		lvm uuid to verify
		:param lvm_id:		lvm_id used to find object
		:return: None
		"""
		# This gets called when we found an object based on lvm_id, ensure
		# uuid is correct too, as they can change
		if lvm_id != uuid:
			if uuid not in self._id_to_object_path:
				obj = self.get_object_by_path(path)
				self._lookup_add(obj, path, lvm_id, uuid)

	def _return_lookup(self, uuid, lvm_identifier):
		"""
		We found an identifier, so lets return the path to the found object
		:param uuid:	The lvm uuid
		:param lvm_identifier: The lvm_id used to find object
		:return:
		"""
		path = self._id_to_object_path[lvm_identifier]
		self._uuid_verify(path, uuid, lvm_identifier)
		return path

	def get_object_path_by_uuid_lvm_id(self, uuid, lvm_id, path_create=None,
										gen_new=True):
		"""
		For a given lvm asset return the dbus object registered to it.  If the
		object is not found and gen_new == True and path_create is a valid
		function we will create a new path, register it and return it.
		:param uuid: The uuid for the lvm object
		:param lvm_id: The lvm name
		:param path_create: If true create an object path if not found
		:param gen_new: The function used to create the new path
		"""
		with self.rlock:
			assert lvm_id
			assert uuid

			if gen_new:
				assert path_create

			path = None

			if lvm_id in self._id_to_object_path:
				self._return_lookup(uuid, lvm_id)

			if "/" in lvm_id:
				vg, lv = lvm_id.split("/", 1)
				int_lvm_id = vg + "/" + ("[%s]" % lv)
				if int_lvm_id in self._id_to_object_path:
					self._return_lookup(uuid, int_lvm_id)
				elif lvm_id.startswith('/'):
					# We could have a pv device path lookup that failed,
					# lets try canonical form and try again.
					canonical = os.path.realpath(lvm_id)
					if canonical in self._id_to_object_path:
						self._return_lookup(uuid, canonical)

			if uuid and uuid in self._id_to_object_path:
				# If we get here it indicates that we found the object, but
				# the lvm_id lookup failed.  In the case of a rename, the uuid
				# will be correct, but the lvm_id will be wrong and vise versa.
				# If the lvm_id does not equal the uuid, lets fix up the table
				# so that lookups will be handled correctly.
				path = self._id_to_object_path[uuid]

				# In some cases we are looking up by one or the other, don't
				# update when they are the same.
				if uuid != lvm_id:
					obj = self.get_object_by_path(path)
					self._lookup_add(obj, path, lvm_id, uuid)
			else:
				if gen_new:
					path = path_create()
					self._lookup_add(None, path, lvm_id, uuid)

			# pprint('get_object_path_by_lvm_id(%s, %s, %s, %s: return %s' %
			#       (uuid, lvm_id, str(path_create), str(gen_new), path))

			return path


class ObjectManagerLock(object):
	"""
	The sole purpose of this class is to allow other code the ability to
	lock the object manager using a `with` statement, eg.

	with cfg.om.locked():
		# Do stuff with object manager

	This will ensure that the lock is always released (assuming this is done
	correctly)
	"""

	def __init__(self, recursive_lock):
		self._lock = recursive_lock

	def __enter__(self):
		# Acquire lock
		self._lock.acquire()

	# noinspection PyUnusedLocal
	def __exit__(self, e_type, e_value, e_traceback):
		# Release lock
		self._lock.release()
		self._lock = None
