# $Id$
#
# parent class for all plugins of the CryptoBox
#

import os
import cherrypy


class CryptoBoxPlugin:

	## default capability is "system" - the other supported capability is: "volume"
	pluginCapabilities = [ "system" ]

	## where should the plugin be visible by default?
	pluginVisibility = [ "preferences" ]

	## does this plugin require admin authentification?
	requestAuth = False

	## default rank (0..100) of the plugin in listings (lower value means higher priority)
	rank = 80


	## default icon of this plugin (relative path)
	defaultIconFileName = "plugin_icon.gif"

	## fallback icon file (in the common plugin directory)
	fallbackIconFileName = "plugin_icon_unknown.gif"


	def __init__(self, cbox, pluginDir):
		self.cbox = cbox
		self.hdf = {}
		self.pluginDir = pluginDir
		self.hdf_prefix = "Data.Plugins.%s." % self.getName()



	def doAction(self, **args):
		"""override doAction with your plugin code"""
		raise Exception, "undefined action handler ('doAction') in plugin '%'" % self.getName()
	

	def getStatus(self):
		"""you should override this, to supply useful state information"""
		raise Exception, "undefined state handler ('getStatus') in plugin '%'" % self.getName()
	

	def getName(self):
		"""the name of the python file (module) should be the name of the plugin"""
		return self.__module__
	

	@cherrypy.expose
	def getIcon(self, image=None, **kargs):
		"""return the image data of the icon of the plugin
		
		the parameter 'image' may be used for alternative image locations (relative
		to the directory of the plugin)
		'**kargs' is necessary, as a 'weblang' attribute may be specified (and ignored)"""
		import cherrypy, re
		if (image is None): # or (re.search(u'[\w-\.]', image)):
			plugin_icon_file = os.path.join(self.pluginDir, self.defaultIconFileName)
		else:
			plugin_icon_file = os.path.join(self.pluginDir, image)
		if not os.access(plugin_icon_file, os.R_OK):
			plugin_icon_file = os.path.join(self.cbox.prefs["Locations"]["PluginDir"], self.fallbackIconFileName)
		return cherrypy.lib.cptools.serveFile(plugin_icon_file)


	def getTemplateFileName(self, template_name):
		"""return the filename of the template, if it is part of this plugin

		use this function to check, if the plugin provides the specified template
		"""
		result_file = os.path.join(self.pluginDir, template_name + ".cs")
		if os.access(result_file, os.R_OK) and os.path.isfile(result_file):
			return result_file
		else:
			return None


	def getLanguageData(self, lang="en"):
		try:
			import neo_cgi, neo_util
		except:
			raise CryptoBoxExceptions.CBEnvironmentError("couldn't import 'neo_*'! Try 'apt-get install python-clearsilver'.")
		langdir = os.path.abspath(os.path.join(self.pluginDir, "lang"))
		## first: the default language file (english)
		langFiles = [os.path.join(langdir, "en.hdf")]
		## maybe we have to load a translation afterwards
		if lang != "en":
			langFiles.append(os.path.join(langdir, lang + ".hdf"))
		file_found = False
		lang_hdf = neo_util.HDF()
		for langFile in langFiles:
			if os.access(langFile, os.R_OK):
				lang_hdf.readFile(langFile)
				file_found = True
		if file_found:
			return lang_hdf
		else:
			self.cbox.log.debug("Couldn't find a valid plugin language file (%s)" % str(langFiles))
			return None


	def loadDataSet(self, hdf):
		for (key, value) in self.hdf.items():
			hdf.setValue(key, str(value))


	def isAuthRequired(self):
		"""check if this plugin requires authentication
		first step: check plugin configuration
		second step: check default value of plugin"""
		try:
			if self.cbox.prefs.pluginConf[self.getName()]["requestAuth"] is None:
				return self.requestAuth
			if self.cbox.prefs.pluginConf[self.getName()]["requestAuth"]:
				return True
			else:
				return False
		except KeyError:
			return self.requestAuth


	def isEnabled(self):
		"""check if this plugin is enabled
		first step: check plugin configuration
		second step: check default value of plugin"""
		fallback = bool(self.pluginVisibility)
		try:
			if self.cbox.prefs.pluginConf[self.getName()]["visibility"] is None:
				return fallback
			return bool(self.cbox.prefs.pluginConf[self.getName()]["visibility"])
		except KeyError:
			return fallback


	def getRank(self):
		"""check the rank of this plugin
		first step: check plugin configuration
		second step: check default value of plugin"""
		try:
			if self.cbox.prefs.pluginConf[self.getName()]["rank"] is None:
				return self.rank
			return int(self.cbox.prefs.pluginConf[self.getName()]["rank"])
		except (KeyError, TypeError):
			return self.rank
	

	def getVisibility(self):
		try:
			if self.cbox.prefs.pluginConf[self.getName()]["visibility"] is None:
				return self.pluginVisibility[:]
			return self.cbox.prefs.pluginConf[self.getName()]["visibility"]
		except KeyError:
			return self.pluginVisibility


	def getTestClass(self):
		import imp
		pl_file = os.path.join(self.pluginDir, "unittests.py")
		if os.access(pl_file, os.R_OK) and os.path.isfile(pl_file):
			try:
				return getattr(imp.load_source("unittests_%s" % self.getName(), pl_file), "unittests")
			except AttributeError:
				pass
		try:
			self.cbox.log.info("could not load unittests for plugin: %s" % self.getName())
		except AttributeError:
			pass
		return None

