#
#	THIS FILE IS PART OF THE JOKOSHER PROJECT AND LICENSED UNDER THE GPL. SEE
#	THE 'COPYING' FILE FOR DETAILS
#
#	This module shows the Extensions Manager dialog which is used to add, remove
#	and configure Jokosher's Extensions.
#
#-------------------------------------------------------------------------------

import gtk.glade, pango
import Globals, Extension
import gettext
import os
import gettext
_ = gettext.gettext

class ExtensionManagerDialog:
	"""
	This module shows the Extensions Manager dialog which is used to add, remove
	and configure Jokosher's Extensions.
	"""
	def __init__(self, parent):
		"""
		Creates a new instance of ExtensionManagerDialog.
		
		Parameters:
			parent -- the parent MainApp Jokosher window.
		"""
		self.parent = parent
		
		self.wTree = gtk.glade.XML(Globals.GLADE_PATH, "ExtensionManagerDialog")
		
		signals = {
			"on_Close_clicked" : self.OnClose,
			"on_Add_clicked" : self.OnAdd,
			"on_Remove_clicked": self.OnRemove,
			"on_Treeview_selected": self.OnSelect,
			"on_Preferences_clicked": self.OnPreferences
		}
		self.wTree.signal_autoconnect(signals)
		
		self.dlg = self.wTree.get_widget("ExtensionManagerDialog")
		self.tree = self.wTree.get_widget("treeviewExtensions")
		self.eb = self.wTree.get_widget("descriptionEventBox")
		self.description = self.wTree.get_widget("ExtensionDescription")
		self.prefs_button = self.wTree.get_widget("buttonPreferences")
		
		self.AddColumn("Enabled", 0, 'toggle')
		self.AddColumn("Name", 1, 'text', 30)
		self.AddColumn("Version", 3, 'text', 7)

		self.model = gtk.ListStore(bool, str, str, str, str, bool)
		self.tree.set_model(self.model)

		for extension in self.parent.extensionManager.GetExtensions():
			self.model.append((extension["enabled"], extension["name"], extension["description"], extension["version"], extension["filename"], extension["preferences"]))


		self.dlg.set_transient_for(self.parent.window)
		self.dlg.show()
	
	#_____________________________________________________________________

	def OnClose(self, button):
		"""
		Destroys the dialog when the close button is pressed.
		It also saves the Extensions's settings.
		
		Parameters:
			button -- reserved for GTK callbacks, don't use it explicitly.
		"""
		self.dlg.destroy()
		Globals.settings.write()
	#_____________________________________________________________________

	def AddColumn(self, title, modelId, cell_renderer='text', cell_width=20):
		"""
		Adds a display column to the ExtensionManager dialog.
		
		Parameters:
			title -- title of the column.
			modelId -- index of the column within the TreeView model.
			cell_renderer -- type of render to use:
							'text' = renders text into the TreeView.
							'toggle' = renders toggle buttons into the TreeView.
			cell_width -- width in pixels of the column.
		"""
		if cell_renderer == 'toggle':
			renderer = gtk.CellRendererToggle()
			renderer.set_property('activatable', True)
			column = gtk.TreeViewColumn(title, renderer, active=modelId)
			renderer.connect('toggled', self.ToggleEnabled)
		
		else:
			renderer = gtk.CellRendererText()
			renderer.set_property('ellipsize', pango.ELLIPSIZE_END)
			renderer.set_property('ellipsize-set', True)
			renderer.set_property('width-chars', cell_width)
			column = gtk.TreeViewColumn(title, renderer, text=modelId)
			column.set_property('resizable', True)

		self.tree.append_column(column)
	
	#_____________________________________________________________________

	def ToggleEnabled(self, cell, path):
		"""
		Enables/disables an Extension.
		
		Parameters:
			cell -- reserved for GTK callbacks, don't use it explicitly.
			path -- path to the Extension.
		"""
		self.model[path][0] = not self.model[path][0]
		
		iter = self.model.get_iter(path)
		name = self.model.get_value(iter, 1)
		filename = self.model.get_value(iter, 4)
		
		if self.model[path][0]:
			if name in Globals.settings.extensions['extensions_blacklist']:
				Globals.settings.extensions['extensions_blacklist'] = Globals.settings.extensions['extensions_blacklist'].replace(name, "")
				Globals.debug("extension-blacklist:", Globals.settings.extensions['extensions_blacklist'])
				for extension in self.parent.extensionManager.GetExtensions():
					if filename == extension['filename']:
						extension['enabled'] = True

				self.parent.extensionManager.StartExtension(filename)
		else:
			if name not in Globals.settings.extensions['extensions_blacklist']:
				Globals.settings.extensions['extensions_blacklist'] += name+" "
				self.parent.extensionManager.StopExtension(filename)
				
				for extension in self.parent.extensionManager.GetExtensions():
					if filename == extension['filename']:
						extension['enabled'] = False
	#_____________________________________________________________________

	def OnSelect(self, tree):
		"""
		When an Extension is selected, enables/disables the preferences button
		according to the reported Extension capabilities and updates the
		description label.
		
		Parameters:
			tree -- GTKTreeView holding the Extensions's representation.
		"""
		descr_text = ""
		selection = self.tree.get_selection().get_selected()[1]
		if selection:
			preferences = self.model.get_value(selection, 5)
			if preferences:
				self.prefs_button.set_sensitive(True)
			else:
				self.prefs_button.set_sensitive(False)
		
			descr_text = self.model.get_value(selection, 2)
		self.description.set_text(descr_text)
	#_____________________________________________________________________
	
	def OnAdd(self, button):
		"""
		Displays a dialog which allows the user to add an external Extension.
		If an error occurs, an error dialog is displayed.
		
		Parameters:
			button -- reserved for GTK callbacks, don't use it explicitly.
		"""
		chooser = gtk.FileChooserDialog((_('Choose a Jokosher Extension file')), None, 
				gtk.FILE_CHOOSER_ACTION_OPEN, (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK))
		chooser.set_default_response(gtk.RESPONSE_OK)
		chooser.set_transient_for(self.dlg)

		filter = gtk.FileFilter()
		filter.set_name(_("Jokosher Extension Files (*.py *.egg)"))
		filter.add_pattern("*.py")
		filter.add_pattern("*.egg")

		chooser.add_filter(filter)

		response = chooser.run()
			
		if response == gtk.RESPONSE_OK:
			install_dlg = gtk.MessageDialog(None, gtk.DIALOG_MODAL, gtk.MESSAGE_QUESTION, 
					gtk.BUTTONS_YES_NO, "Install extension to local jokosher extension directory?")
			install_response = install_dlg.run()
			
			if install_response == gtk.RESPONSE_YES:
				filename = chooser.get_filename()
				#TODO: redo the enable/disable stuff here
				
				if not self.parent.extensionManager.LoadExtensionFromFile(os.path.basename(filename), os.path.dirname(filename), local=True):
					dlg = gtk.MessageDialog(self.dlg,
						gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
						gtk.MESSAGE_ERROR,
						gtk.BUTTONS_CLOSE,
						_("There was a problem loading the extension"))
					dlg.run()
					dlg.destroy()
				self.UpdateModel()
				chooser.destroy()
			
			else:
				install_dlg.destroy()
			install_dlg.destroy()	
								
		chooser.destroy()
	
	#_____________________________________________________________________

	def OnRemove(self, button):
		"""
		Removes an Extension from the Extensions list.
		If an error occurs, an error dialog is displayed.
		
		Parameters:
			button -- reserved for GTK callbacks, don't use it explicitly.
		"""
		selection = self.tree.get_selection()
		row_selected = selection.get_selected()[1]
		filename = self.model.get_value(row_selected, 4)
		
		if row_selected:
			if Extension.EXTENSION_DIR_USER in filename:
				dlg = gtk.MessageDialog(None, gtk.DIALOG_MODAL, gtk.MESSAGE_QUESTION, 
						gtk.BUTTONS_YES_NO, "Remove the selected extension?")
				response = dlg.run()
				if response == gtk.RESPONSE_YES:
					dlg.destroy()
					if not self.parent.extensionManager.RemoveExtension(filename): #don't forget to change to RemoveExtenion() in ExtensionManager
						dlg2 = gtk.MessageDialog(self.dlg,
							gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
							gtk.MESSAGE_ERROR,
							gtk.BUTTONS_CLOSE,
							_("There was a problem removing the extension"))
						dlg2.run()
						dlg2.destroy()
						
					self.UpdateModel()
				
				dlg.destroy()

			else:
				dlg = gtk.MessageDialog(None, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR,
						gtk.BUTTONS_OK, "This extension was installed by your system. You cannot remove it.")
				dlg.run()
				dlg.destroy()
		else:
			dlg = gtk.MessageDialog(None, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR,
					gtk.BUTTONS_OK, "No extension selected!")
			dlg.run()
			dlg.destroy()

	#_____________________________________________________________________

	def OnPreferences(self, button):
		"""
		Displays the Extension's preferences dialog.
		If an error occurs, an error dialog is displayed.
		
		Parameters:
			button -- reserved for GTK callbacks, don't use it explicitly.
		"""
		selection = self.tree.get_selection().get_selected()[1]
		filename = self.model.get_value(selection, 4)

		if not self.parent.extensionManager.ExtensionPreferences(filename):
			dlg = gtk.MessageDialog(self.dlg,
							gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
							gtk.MESSAGE_ERROR,
							gtk.BUTTONS_CLOSE,
							_("An error occurred when trying to launch the preferences for the extension"))
			dlg.run()
			dlg.destroy()

	#_____________________________________________________________________

	def UpdateModel(self):
		"""
		Updates the ExtensionManagerDialog Extension list, to reflect changes
		in the currently available Extensions.
		"""
		selection = self.tree.get_selection()
		row_selected = selection.get_selected()[1]
		
		num_extensions = len(self.parent.extensionManager.loadedExtensions)
		num_model = len(self.model)
		
		if num_model < num_extensions:
			extension = self.parent.extensionManager.loadedExtensions[num_extensions-1]
			self.model.append((extension["enabled"], extension["name"], extension["description"], extension["version"], extension["filename"], extension["preferences"]))
		
		elif num_model > num_extensions:
			self.model.remove(row_selected)

	#_____________________________________________________________________
