import os.path
from sets import Set as set

from PyQt4.uic.exceptions import NoSuchWidgetError, WidgetPluginError


MATCH = True
NO_MATCH = False
MODULE = 0
CW_FILTER = 1


class QObjectCreator(object):    
    def __init__(self, creatorPolicy):
        self._cpolicy = creatorPolicy
        
        self._cwFilters = []
        self._modules = [self._cpolicy.createQtGuiWrapper()]

        # Get the optional plugins.
        plugindir = os.path.join(os.path.split(__file__)[0],
                                 "widget-plugins")

        try:
            plugins = os.listdir(plugindir)
        except:
            plugins = []

        for filename in plugins:
            if not filename.endswith(".py"):
                continue
            plugin_globals = {"MODULE" : MODULE,
                              "CW_FILTER" : CW_FILTER,
                              "MATCH": MATCH,
                              "NO_MATCH": NO_MATCH}
            plugin_locals = {}
            try:
                execfile(os.path.join(plugindir, filename),
                         plugin_globals, plugin_locals)
                pluginType = plugin_locals["pluginType"]
                if pluginType == MODULE:
                    modinfo = plugin_locals["moduleInformation"]()
                    self._modules.append(self._cpolicy.createModuleWrapper(*modinfo))
                elif pluginType == CW_FILTER:
                    self._cwFilters.append(plugin_locals["getFilter"]())
                else:
                    raise WidgetPluginError, "Unknown plugin type of %s" % (filename,)
            except ImportError:
                # plugins may raise an import error to be ignored
                pass
            except Exception, e:
                # TODO: what about exception chaining?
                raise WidgetPluginError, "%s: %s" % (e.__class__, str(e))
            
            
        self._customWidgets = self._cpolicy.createCustomWidgetLoader()
        self._modules.append(self._customWidgets)

    def createQObject(self, classname, *args, **kwargs):
        classType = self.findQObjectType(classname)
        if classType:
            return self._cpolicy.instantiate(classType, *args, **kwargs)
        raise NoSuchWidgetError, classname

    def invoke(self, rname, method, args=()):
        return self._cpolicy.invoke(rname, method, args)

    def findQObjectType(self, classname):
        for module in self._modules:
            w = module.search(classname)
            if w is not None:
                return w
        return None

    def getSlot(self, obj, slotname):
        return self._cpolicy.getSlot(obj, slotname)
                                 
    def addCustomWidget(self, widgetClass, baseClass, module):
        for cwFilter in self._cwFilters:
            match, result = cwFilter(widgetClass, baseClass, module)
            if match:
                widgetClasse, baseClass, module = result
                break

        self._customWidgets.addCustomWidget(widgetClass, baseClass, module)
