from django.utils.encoding import smart_str, force_unicode


USE_CPICKLE = getattr(settings, 'USE_CPICKLE', False)

if USE_CPICKLE:
    import cPickle as pickle
else:
    import pickle

class BaseSifrelenmisField(models.Field):
  
    def __init__(self, *args, **kwargs):
        cipher = kwargs.pop('cipher', 'AES')
        try:
            imp = __import__('Crypto.Cipher', globals(), locals(), [cipher], -1)
        except:
            imp = __import__('Crypto.Cipher', globals(), locals(), [cipher])
        self.cipher = getattr(imp, cipher).new(settings.SECRET_KEY[:32])
        self.prefix = '$%s$' % cipher

        max_length = kwargs.get('max_length', 40)
        self.cozulmus_length = max_length
      
        max_length += 2
        mod = max_length % self.cipher.block_size
        if mod > 0:
            max_length += self.cipher.block_size - mod
        kwargs['max_length'] = max_length * 2 + len(self.prefix)

        models.Field.__init__(self, *args, **kwargs)

    def _is_sifrelenmis(self, value):
        return isinstance(value, basestring) and value.startswith(self.prefix)

    def _getir_karatablo_siralama(self, value):
       
        mod = (len(value) + 2) % self.cipher.block_size
        return self.cipher.block_size - mod + 2


    def to_python(self, value):
        if self._is_sifrelenmis(value):
            return force_unicode(
                self.cipher.decrypt(
                    binascii.a2b_hex(value[len(self.prefix):])
                ).split('\0')[0]
            )
        return value

    def getir_db_ve_hazirla(self, value):
        value = smart_str(value)

        if value is not None and not self._is_sifrelenmis(value):
            padding = self._getir_karatablo_siralama(value)
            if padding > 0:
                value += "\0" + ''.join([random.choice(string.printable)
                    for index in range(padding-1)])
            value = self.prefix + binascii.b2a_hex(self.cipher.encrypt(value))
        return value


class SifrelenmisTextField(BaseSifrelenmisField):
    __metaclass__ = models.SubfieldBase

    def getir_ic_kulanilan(self):
        return 'TextField'

    def formfield(self, **kwargs):
        defaults = {'widget': forms.Textarea}
        defaults.update(kwargs)
        return super(SifrelenmisTextField, self).formfield(**defaults)


class SifrelenmisCharField(BaseSifrelenmisField):
    __metaclass__ = models.SubfieldBase

    def getir_ic_kulanilan(self):
        return "CharField"

    def formfield(self, **kwargs):
        defaults = {'max_length': self.max_length}
        defaults.update(kwargs)
        return super(SifrelenmisCharField, self).formfield(**defaults)

    def getir_db_ve_hazirla(self, value):
        if value is not None and not self._is_sifrelenmis(value):
            if len(value) > self.cozulmus_length:
                raise ValueError("Field value longer than max allowed: " +
                    str(len(value)) + " > " + str(self.cozulmus_length))
        return super(SifrelenmisCharField, self).getir_db_ve_hazirla(value)