import os
from PyQt4 import QtCore, QtGui, uic
from tools import AbstractRegister 

def fromVariant(v):
    _cvrts = {0: lambda x:None,
              1: lambda x:x.toBool(),
              2: lambda x:x.toInt()[0],
              6: lambda x:x.toDouble()[0],
              10: lambda x:unicode(x.toString()),
              12: lambda x:x.toByteArray(),
              21: lambda x:x.toSize(),
              22: lambda x:x.toSizeF(),
              25: lambda x:x.toPoint(),
              26: lambda x:x.toPointF(),
              64: lambda x:QtGui.QFont(x),
              67: lambda x:QtGui.QColor(x),
              }
    t = v.userType()
    return _cvrts[t](v)

class PreferenceMetaclass(type):
    _widgets = {}
    def __init__(cls, name, bases, dct):
        # called at class creation
        super(type, cls).__init__(name, bases, dct)
        if name != "BaseItem":
            ItemRegister().add(cls)

class BaseItem(object):
    #__metaclass__ = PreferenceMetaclass
    _id = 0
    def __init__(self, default=None, name=None, description=None, group=None):
        self._default = default
        self._id = BaseItem._id
        self._name = name
        self._description = description
        self._group = group
        BaseItem._id += 1

    def validate(self, value):
        return True
    
    def __get__(self, obj, cls):
        if obj is None: #when called from the class, return the Item itself
            return self
        try:
            return obj.getPref(self._id)
        except Exception, e:
            return None

    def __set__(self, obj, value):
        obj.setPref(self._id, value)

class ItemRegister(AbstractRegister):
    _registered_type = BaseItem
    getItem = AbstractRegister.get_class

class PointItem(BaseItem):
    _type = QtCore.QPoint

class SizeItem(BaseItem):
    _type = QtCore.QSize

class ByteArrayItem(BaseItem):
    _type = QtCore.QByteArray
    
class UnicodeItem(BaseItem):
    _type = unicode
    def validate(self, value):
        return isinstance(value, basestring)
        
class IntItem(BaseItem):
    _type = int
    def __init__(self, default=None, name=None, description=None, group=None, min=None, max=None):
        BaseItem.__init__(self, default, name, description, group)
        self._min = min
        self._max = max

    def validate(self, value):
        try:
            value = self._type(value)
        except:
            return False
        if self._min is not None and value<self._min:
            return False
        if self._max is not None and value>self._max:
            return False
        return True

class ColorItem(BaseItem):
    _type = QtGui.QColor

    def validate(self, value):
        try:
            self._type(value)
            return True
        except:
            return False
    
class AbstractPreferences(QtCore.QObject):
    def __init__(self):
        QtCore.QObject.__init__(self)
        self._settings = QtCore.QSettings(QtCore.QSettings.UserScope,
                                          self.ORGANISATION, self.APPLICATION)
        self._prefs = {}
        self.groups = []
        keys = []
        for k in dir(self.__class__):
            item = self.getItem(k)
            if isinstance(item, BaseItem):
                keys.append((k,item))
        keys.sort(key=lambda x: x[1]._id)
        for k, item in keys:
            self._prefs[item._id] = k
            if item._group not in self.groups:
                self.groups.append(item._group)

    def getItem(self, key):
        return getattr(self.__class__, key)
        #return self._prefs.get(key, None)
    
    def getPref(self, key):
        key = self._prefs.get(key, key)
        default = getattr(self.__class__, key)._default
        if default is not None:
            default = QtCore.QVariant(default)
        else:
            default = QtCore.QVariant()
        val = fromVariant(self._settings.value(key, default))
        return val
    
    def setPref(self, key, value):
        key = self._prefs.get(key, key)
        self._settings.setValue(key, QtCore.QVariant(value))

    def keys(self, group=None):
        return [k for k in self._prefs.values() if not k.startswith('_') and self.getItem(k)._group == group]

    def getName(self, key):
        item = getattr(self.__class__, key)
        return item._name

    def getDescription(self, key):
        item = getattr(self.__class__, key)
        return item._description

    def __getitem__(self, key):
        return getattr(self, key)
    
