# 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 dbus
from . import cfg
from .utils import get_properties, add_properties, get_object_property_diff, \
	log_debug
from .state import State


# noinspection PyPep8Naming,PyUnresolvedReferences
class AutomatedProperties(dbus.service.Object):
	"""
	This class implements the needed interfaces for:
	org.freedesktop.DBus.Properties

	Other classes inherit from it to get the same behavior
	"""

	def __init__(self, object_path, search_method=None):
		dbus.service.Object.__init__(self, cfg.bus, object_path)
		self._ap_interface = []
		self._ap_o_path = object_path
		self._ap_search_method = search_method
		self.state = None

	def dbus_object_path(self):
		return self._ap_o_path

	def emit_data(self):
		props = {}

		for i in self.interface():
			props[i] = self.GetAll(i)

		return self._ap_o_path, props

	def set_interface(self, interface):
		"""
		With inheritance we can't easily tell what interfaces a class provides
		so we will have each class that implements an interface tell the
		base AutomatedProperties what it is they do provide.  This is kind of
		clunky and perhaps we can figure out a better way to do this later.
		:param interface:       An interface the object supports
		:return:
		"""
		if interface not in self._ap_interface:
			self._ap_interface.append(interface)

	# noinspection PyUnusedLocal
	def interface(self, all_interfaces=False):
		if all_interfaces:
			cpy = list(self._ap_interface)
			cpy.extend(
				["org.freedesktop.DBus.Introspectable",
					"org.freedesktop.DBus.Properties"])
			return cpy

		return self._ap_interface

	# Properties
	# noinspection PyUnusedLocal
	@dbus.service.method(dbus_interface=dbus.PROPERTIES_IFACE,
							in_signature='ss', out_signature='v')
	def Get(self, interface_name, property_name):
		value = getattr(self, property_name)
		# Note: If we get an exception in this handler we won't know about it,
		# only the side effect of no returned value!
		log_debug('Get (%s), type (%s), value(%s)' %
					(property_name, str(type(value)), str(value)))
		return value

	@dbus.service.method(dbus_interface=dbus.PROPERTIES_IFACE,
							in_signature='s', out_signature='a{sv}')
	def GetAll(self, interface_name):
		if interface_name in self.interface(True):
			# Using introspection, lets build this dynamically
			properties = get_properties(self)
			if interface_name in properties:
				return properties[interface_name][1]
			return {}
		raise dbus.exceptions.DBusException(
			self._ap_interface,
			'The object %s does not implement the %s interface'
			% (self.__class__, interface_name))

	@dbus.service.method(dbus_interface=dbus.PROPERTIES_IFACE,
							in_signature='ssv')
	def Set(self, interface_name, property_name, new_value):
		setattr(self, property_name, new_value)
		self.PropertiesChanged(interface_name,
								{property_name: new_value}, [])

	# As dbus-python does not support introspection for properties we will
	# get the autogenerated xml and then add our wanted properties to it.
	@dbus.service.method(dbus_interface=dbus.INTROSPECTABLE_IFACE,
							out_signature='s')
	def Introspect(self):
		r = dbus.service.Object.Introspect(self, self._ap_o_path, cfg.bus)
		# Look at the properties in the class
		props = get_properties(self)

		for int_f, v in props.items():
			r = add_properties(r, int_f, v[0])

		return r

	@dbus.service.signal(dbus_interface=dbus.PROPERTIES_IFACE,
							signature='sa{sv}as')
	def PropertiesChanged(self, interface_name, changed_properties,
							invalidated_properties):
		log_debug(('SIGNAL: PropertiesChanged(%s, %s, %s, %s)' %
					(str(self._ap_o_path), str(interface_name),
					str(changed_properties), str(invalidated_properties))))

	def refresh(self, search_key=None, object_state=None):
		"""
		Take the values (properties) of an object and update them with what
		lvm currently has.  You can either fetch the new ones or supply the
		new state to be updated with
		:param search_key: The value to use to search for
		:param object_state: Use this as the new object state
		"""
		num_changed = 0

		# If we can't do a lookup, bail now, this happens if we blindly walk
		# through all dbus objects as some don't have a search method, like
		# 'Manager' object.
		if not self._ap_search_method:
			return

		search = self.lvm_id
		if search_key:
			search = search_key

		# Either we have the new object state or we need to go fetch it
		if object_state:
			new_state = object_state
		else:
			new_state = self._ap_search_method([search])[0]
			assert isinstance(new_state, State)

		assert new_state

		# When we refresh an object the object identifiers might have changed
		# because LVM allows the user to change them (name & uuid), thus if
		# they have changed we need to update the object manager so that
		# look-ups will happen correctly
		old_id = self.state.identifiers()
		new_id = new_state.identifiers()
		if old_id[0] != new_id[0] or old_id[1] != new_id[1]:
			cfg.om.lookup_update(self, new_id[0], new_id[1])

		# Grab the properties values, then replace the state of the object
		# and retrieve the new values
		# TODO: We need to add locking to prevent concurrent access to the
		# properties so that a client is not accessing while we are
		# replacing.
		o_prop = get_properties(self)
		self.state = new_state
		n_prop = get_properties(self)

		changed = get_object_property_diff(o_prop, n_prop)

		if changed:
			for int_f, v in changed.items():
				self.PropertiesChanged(int_f, v, [])
			num_changed += 1
		return num_changed
