############################################################################
#    Copyright (C) 2005 by Manuel Amador (Rudd-O)                          #
#    rudd-o@amautacorp.com                                                 #
#                                                                          #
#    This program is free software; you can redistribute it and#or modify  #
#    it under the terms of the GNU General Public License as published by  #
#    the Free Software Foundation; either version 2 of the License, or     #
#    (at your option) any later version.                                   #
#                                                                          #
#    This program is distributed in the hope that it will be useful,       #
#    but WITHOUT ANY WARRANTY; without even the implied warranty of        #
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         #
#    GNU General Public License for more details.                          #
#                                                                          #
#    You should have received a copy of the GNU General Public License     #
#    along with this program; if not, write to the                         #
#    Free Software Foundation, Inc.,                                       #
#    59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             #
############################################################################

# FIXME implement an interface that allows the indexer to compare in-store file objects' interface versions with its corresponding plugin"s interface version, to provide for automatic schema migration.  Bump the interface number on your plugin, and pof all files are automatically reindexed when they are modified (or perhaps upon startup/reload)
# FIXME implement an observer pattern so that the index database detects when the plugins are reloaded, suspend database access to client classes, run __prepare_indexes and refresh objects whose interfaces have changed (ay que pensar bien el orden de mierda de estas operaciones para que no se vaya todo a la verga"), 

import os
from MetadataService.Component import Component
import platform

import PluginInterface
import __builtin__
__builtin__.PluginInterface = PluginInterface

class FilePluginManager(Component):

	mimetype_plugin_map = {}
	log = None

	def __init__(self):
		Component.__init__(self,public_interface=None)
		self.set_component_name("FilesystemAgent.FilePluginManager")
		self.reload_plugins()

	def reload_plugins(self):
		#Fixme: need to implement observer pattern so index database can rebuild indexes as necessary, or perhaps the indexer determines what indexes to build in a different way, seeing that there are different infospaces to build into this service in the medium-term future
		
		self._new_mimetype_plugin_map = {}
		self.load_plugins()
		self.mimetype_plugin_map = self._new_mimetype_plugin_map
# 		self.log.debug("Mimetypes registered: %s",str(self.mimetype_plugin_map))
	

	def load_plugin(self,plugin):
		if plugin == "__init__.py": return # do not load __init__.py!
		import imp
		module_name = plugin[0:len(plugin)-len(".py")]
		
		try: fd, filename, module_info = imp.find_module(module_name,[self.get_plugin_path()])
		except ImportError: raise IOError,(13,"Permission denied: '%s'"%a)
		
		module = imp.load_module(module_name,fd,filename,module_info)
		fd.close()
		
		if module.__dict__.has_key("get_mimetypes") and module.__dict__.has_key("get_factory"):
			# only then we'll consider the module as a plugin
			for mimetype in module.get_mimetypes():
				self._new_mimetype_plugin_map[mimetype] = module.get_factory()
			self.log.debug("Loaded plugin ("+plugin+"), handling " + str(module.get_mimetypes()))
		else: self.log.warning("Not a plugin: " + plugin)

	def get_plugin_path(self):
		import FilePluginManager
		return os.path.join(os.path.dirname(FilePluginManager.__file__),"plugins")
		
	def load_plugins(self):
		self.log.debug("Loading indexer plugins")
		olddir = os.getcwd()
		os.chdir(self.get_plugin_path())
		pluginextension = ".py"
		from glob import glob
		pythonpluginfiles = glob("*"+pluginextension)
		os.chdir(olddir)
		for a in pythonpluginfiles:
			try: self.load_plugin(a)
			except ImportError, e:
				self.log.warning("Plugin %s requires unavailable libraries or is unreadable",a,exc_info=False) # we need a global function or construct which can let us do exc_info = IfDebug, and a debugging config switch
			except IOError, e: self.log.warning("Plugin %s cannot be opened for reading",a,exc_info=True)
			except: self.log.warning("Cannot load %s",a,exc_info=True)
		self.log.info("Indexer plugins loaded")

	def get_factory_for_mimetype(self,mimetype):
		assert type(mimetype) is str and len(mimetype) > 0
		if self.mimetype_plugin_map.has_key(mimetype): return self.mimetype_plugin_map[mimetype]
		return None
	
	def get_information_object(self,filename,volume):
		from InfospaceObjects import Volume
		assert isinstance(volume,Volume)
		assert type(filename) is str and len(filename) > 0
		mimetype = platform.get_mimetype(filename)
		if mimetype is None: mimetype = "application/octet-stream" # just in case no mimetype is detected!
		factory = self.get_factory_for_mimetype(mimetype)
		if factory is None: #we'll default to builtins
			if os.path.isdir(filename):
				from Directory import Directory
				factory = Directory
			else:
				from File import File
				factory = File
		object = factory(filename=filename,volume=volume,mimetype=mimetype)
		return object
