import gettext, copy
_ = gettext.gettext

"""
"1.2.36.79672281.1.5.0": RDN
"1.3.6.1.1.1.0.0": RFC2307 NIS Netgroup Triple
"1.3.6.1.1.1.0.1": RFC2307 Boot Parameter
"1.3.6.1.1.16.1": UUID
"1.3.6.1.4.1.1466.115.121.1.10": Certificate Pair
"1.3.6.1.4.1.1466.115.121.1.11": Country String
"1.3.6.1.4.1.1466.115.121.1.12": Distinguished Name
"1.3.6.1.4.1.1466.115.121.1.14": Delivery Method
"1.3.6.1.4.1.1466.115.121.1.15": Directory String
"1.3.6.1.4.1.1466.115.121.1.22": Facsimile Telephone Number
"1.3.6.1.4.1.1466.115.121.1.24": Generalized Time
"1.3.6.1.4.1.1466.115.121.1.26": IA5 String
"1.3.6.1.4.1.1466.115.121.1.27": Integer
"1.3.6.1.4.1.1466.115.121.1.28": JPEG
"1.3.6.1.4.1.1466.115.121.1.34": Name And Optional UID
"1.3.6.1.4.1.1466.115.121.1.36": Numeric String
"1.3.6.1.4.1.1466.115.121.1.38": OID
"1.3.6.1.4.1.1466.115.121.1.39": Other Mailbox
"1.3.6.1.4.1.1466.115.121.1.4": Audio
"1.3.6.1.4.1.1466.115.121.1.40": Octet String
"1.3.6.1.4.1.1466.115.121.1.41": Postal Address
"1.3.6.1.4.1.1466.115.121.1.44": Printable String
"1.3.6.1.4.1.1466.115.121.1.45": SubtreeSpecification
"1.3.6.1.4.1.1466.115.121.1.49": Supported Algorithm
"1.3.6.1.4.1.1466.115.121.1.5": Binary
"1.3.6.1.4.1.1466.115.121.1.50": Telephone Number
"1.3.6.1.4.1.1466.115.121.1.52": Telex Number
"1.3.6.1.4.1.1466.115.121.1.6": Bit String
"1.3.6.1.4.1.1466.115.121.1.7": Boolean
"1.3.6.1.4.1.1466.115.121.1.8": Certificate
"1.3.6.1.4.1.1466.115.121.1.9": Certificate List
"""                                                         
class Attribute(object):
    default = ''
    
    def __deepcopy__(self, memo=None):
        return Attribute(self.attribute_type.name, copy.deepcopy(self.value), self.mandatory, self.visible)
    
    def __init__(self, attribute_type, value = None, mandatory = False, visible = True):

        _type = _attribute_types[attribute_type]
        self.attribute_type = _type['factory']( name = _type['name'],
                                                desc = _type['desc'],
                                                multi_valued = _type['multi_valued'] )
        
        self.mandatory = mandatory
        self.visible = visible
        self.rank = _type['rank']

        if not value:
            self.set( [] )
        else:
            self.set(value)

    def set(self, value):
        self.attribute_type.set(self, value)

    def get(self):
        return self.attribute_type.get(self)

    def asLdap(self):
        return self.attribute_type.asLdap(self)

    def validate(self, value):
        return True


class AttributeType(object):
    def __init__(self, name, desc = '', multi_valued = True):
        self.name = name
        self.desc = desc
        self.multi_valued = multi_valued

    @staticmethod
    def set(attr, value):
        attr.value = value

    @staticmethod
    def get(attr):
        return attr.value
            
    @staticmethod
    def asLdap(attr):
        return attr.value

#
# generic attributes
#
class StringAttribute(AttributeType):
    """A unicode string"""
    pass

class MailAttribute(StringAttribute):
    """A rfc822 mail address"""
    pass

class DNAttribute(AttributeType):
    """A LDAP-compliant distinguish name"""
    def __init__(self, name, desc = '', multi_valued = True, filter_re = '.*'):
        AttributeType.__init__(self, name, desc, multi_valued)
        self.filter_re = filter_re

class TextAttribute(AttributeType):
    """A multi-line unicode string"""

    def validate(self, value):
        return True

class PasswordAttribute(AttributeType):
    """A password"""

    def validate(self, value):
        return True


class BooleanAttribute(AttributeType):
    """A boolean state"""

    @staticmethod
    def set(attr, value):
        if not value or not value[0] or value[0] == 'FALSE':
            attr.value = [ False ]
        else:
            attr.value = [ True ]

    @staticmethod
    def asLdap(attr):
        if attr.value[0]:
            return 'TRUE'
        return 'FALSE'
    
#TODO : guess these from schema
_attribute_types = {
    'cn': { 'factory': StringAttribute, 'name': 'cn', 'desc' : _('cn'), 'multi_valued': False, 'rank': 7 }, #WARNING: ''multi_valued':' differs from schema
    'enabled': { 'factory': BooleanAttribute, 'name': 'enabled', 'desc' : _('enabled'), 'multi_valued': False, 'rank': 6 },
    'hostname': { 'factory': StringAttribute, 'name': 'hostname', 'desc' : _('hostname'), 'multi_valued': False, 'rank': 100 },
    'ldapBaseDN': { 'factory': StringAttribute, 'name': 'ldapBaseDN', 'desc' : _('ldapBaseDN'), 'multi_valued': False, 'rank': 100 },
    'ldapServer': { 'factory': StringAttribute, 'name': 'ldapServer', 'desc' : _('ldapServer'), 'multi_valued': True, 'rank': 100 },
    'lechatMailForward': { 'factory': MailAttribute, 'name': 'lechatMailForward', 'desc' : _('lechatMailForward'), 'multi_valued': True, 'rank': 9 },
    'lechatMailForwardOnly': { 'factory': BooleanAttribute, 'name': 'lechatMailForwardOnly', 'desc' : _('lechatMailForwardOnly'), 'multi_valued': False, 'rank': 10 },
    'lechatMailVacation': { 'factory': BooleanAttribute, 'name': 'lechatMailVacation', 'desc' : _('lechatMailVacation'), 'multi_valued': False, 'rank': 100 },
    'lechatMailVacationInfo': { 'factory': TextAttribute, 'name': 'lechatMailVacationInfo', 'desc' : _('lechatMailVacationInfo'), 'multi_valued': False, 'rank': 100 },
    'lechatUserMainDomain': { 'factory': DNAttribute, 'name': 'lechatUserMainDomain', 'desc' : _('lechatUserMainDomain'), 'multi_valued': False, 'rank': 6 },
    'mail': { 'factory': MailAttribute, 'name': 'mail', 'desc' : _('mail'), 'multi_valued': True, 'rank': 8 },
    'node': { 'factory': StringAttribute, 'name': 'node', 'desc' : _('node'), 'multi_valued': False, 'rank': 5 },
    'objectClass': { 'factory': DNAttribute, 'name': 'objectClass', 'desc': _('objectClass'), 'multi_valued': True, 'rank': 100 },
    'services': { 'factory': StringAttribute, 'name': 'services', 'desc' : _('services'), 'multi_valued': True, 'rank': 100 },
    'sn': { 'factory': StringAttribute, 'name': 'sn', 'desc' : _('sn'), 'multi_valued': False, 'rank': 100 },
    'userPassword': { 'factory': PasswordAttribute, 'name': 'userPassword', 'desc' : _('userPassword'), 'multi_valued': False, 'rank': 10 }, #WARNING: ''multi_valued':' differs from schema
    }


