import os
from cryptobox.core.exceptions import *
import cryptobox.core.container as cbxContainer
import cryptobox.core.tools as cbxTools


class WebInterfaceDataset(dict):
	"""this class contains all data that should be available for the clearsilver
	templates
	"""

	def __init__(self, cbox, prefs, plugins):
		self.prefs = prefs
		self.cbox = cbox
		self.__setConfigValues()
		self.plugins = plugins
		self.setCryptoBoxState()
		self.setPluginData()
		self.setContainersState()


	def setCryptoBoxState(self):
		import cherrypy
		import cryptobox.core.main
		self["Data.Version"] = cryptobox.core.main.VERSION
		langs = self.cbox.getAvailableLanguages()
		langs.sort()
		for (index, lang) in enumerate(langs):
			self.cbox.log.info("language loaded: %s" % lang)
			self["Data.Languages.%d.name" % index] = lang
			self["Data.Languages.%d.link" % index] = self.__getLanguageName(lang)
		try:
			self["Data.ScriptURL.Prot"] = cherrypy.request.scheme
			host = cherrypy.request.headers["Host"]
			self["Data.ScriptURL.Host"] = host.split(":",1)[0]
			complete_url = "%s://%s" % (self["Data.ScriptURL.Prot"], self["Data.ScriptURL.Host"])
			try:
				port = int(host.split(":",1)[1])
				complete_url += ":%s" % port
			except (IndexError, ValueError):
				if cherrypy.request.scheme == "http":
					port = 80
				elif cherrypy.request.scheme == "https":
					port = 443
				else:
					## unknown scheme -> port 0
					self.cbox.log.info("unknown protocol scheme used: %s" % (cherrypy.request.scheme,))
					port = 0
			self["Data.ScriptURL.Port"] = port
			## retrieve the relative address of the CGI (or the cherrypy base address)
			## remove the last part of the url and add a slash
			path = "/".join(cherrypy.request.path.split("/")[:-1]) + "/"
			self["Data.ScriptURL.Path"] = path
			complete_url += path
			self["Data.ScriptURL"] = complete_url
		except AttributeError:
			self["Data.ScriptURL"] = ""


	def setCurrentDiskState(self, device):
		for container in self.cbox.getContainerList():
			if container.getDevice() == device:
				isEncrypted = (container.getType() == cbxContainer.ContainerTypes["luks"]) and 1 or 0
				isPlain = (container.getType() == cbxContainer.ContainerTypes["plain"]) and 1 or 0
				isMounted = container.isMounted() and 1 or 0
				self["Data.CurrentDisk.device"] = container.getDevice()
				self["Data.CurrentDisk.name"] = container.getName()
				self["Data.CurrentDisk.encryption"] = isEncrypted
				self["Data.CurrentDisk.plaintext"] = isPlain
				self["Data.CurrentDisk.active"] = isMounted
				self["Data.CurrentDisk.size"] = cbxTools.getBlockDeviceSizeHumanly(container.getDevice())
				if isMounted:
					(size, avail, used) = container.getCapacity()
					percent = used / size
					self["Data.CurrentDisk.capacity.used"] = used
					self["Data.CurrentDisk.capacity.free"] = avail
					self["Data.CurrentDisk.capacity.size"] = size
					self["Data.CurrentDisk.capacity.percent"] = percent
		self["Settings.LinkAttrs.device"] = device
	

	def setContainersState(self):
		avail_counter  = 0
		active_counter = 0
		for container in self.cbox.getContainerList():
			## useful if the container was changed during an action
			container.resetObject()
			isEncrypted = (container.getType() == cbxContainer.ContainerTypes["luks"]) and 1 or 0
			isPlain = (container.getType() == cbxContainer.ContainerTypes["plain"]) and 1 or 0
			isMounted = container.isMounted() and 1 or 0
			self["Data.Disks.%d.device" % avail_counter] = container.getDevice()
			self["Data.Disks.%d.name" % avail_counter] = container.getName()
			self["Data.Disks.%d.encryption" % avail_counter] = isEncrypted
			self["Data.Disks.%d.plaintext" % avail_counter] = isPlain
			self["Data.Disks.%d.active" % avail_counter] = isMounted
			self["Data.Disks.%d.size" % avail_counter] = cbxTools.getBlockDeviceSizeHumanly(container.getDevice())
			if isMounted: active_counter += 1
			avail_counter += 1
		self["Data.activeDisksCount"] = active_counter
	

	def setPluginData(self):
		for p in self.plugins:
			entryName = "Settings.PluginList." + p.getName()
			## first: remove all existing settings of this plugin
			for key in self.keys():
				if key.startswith(entryName):	del self[key]
			lang_data = p.getLanguageData()
			self[entryName] = p.getName()
			self[entryName + ".Name"] = lang_data.getValue("Name", p.getName())
			self[entryName + ".Link"] = lang_data.getValue("Link", p.getName())
			self[entryName + ".Rank"] = p.getRank()
			self[entryName + ".RequestAuth"] = p.isAuthRequired() and "1" or "0"
			for a in p.pluginCapabilities:
				self[entryName + ".Types." + a] = "1"
			for a in p.getVisibility():
				self[entryName + ".Visible." + a] = "1"


	def __setConfigValues(self):
		self["Settings.TemplateDir"] = os.path.abspath(self.prefs["Locations"]["TemplateDir"])
		self["Settings.LanguageDir"] = os.path.abspath(self.prefs["Locations"]["LangDir"])
		self["Settings.DocDir"] = os.path.abspath(self.prefs["Locations"]["DocDir"])
		self["Settings.Stylesheet"] = self.prefs["WebSettings"]["Stylesheet"]
		self["Settings.Language"] = self.prefs["WebSettings"]["Language"]
		self["Settings.PluginDir"] = self.prefs["Locations"]["PluginDir"]
		self["Settings.SettingsDir"] = self.prefs["Locations"]["SettingsDir"]


	def __getLanguageName(self, lang):
		try:
			import neo_cgi, neo_util, neo_cs
		except:
			raise CBEnvironmentError("couldn't import 'neo_*'! Try 'apt-get install python-clearsilver'.")
		hdf_path = os.path.join(self.prefs["Locations"]["LangDir"], lang + ".hdf")
		hdf = neo_util.HDF()
		hdf.readFile(hdf_path)
		return hdf.getValue("Name",lang)



