import base64
from django.core import validators
from django.db import models
from django.utils.translation import ugettext_lazy as _
import floppyforms as forms
from misago.utils.timezones import tzlist
try:
    import cPickle as pickle
except ImportError:
    import pickle

class Setting(models.Model):
    setting = models.CharField(max_length=255, primary_key=True)
    group = models.ForeignKey('SettingsGroup', to_field='key')
    _value = models.TextField(db_column='value', null=True, blank=True)
    value_default = models.TextField(null=True, blank=True)
    normalize_to = models.CharField(max_length=255)
    field = models.CharField(max_length=255)
    extra = models.TextField(null=True, blank=True)
    position = models.IntegerField(default=0)
    separator = models.CharField(max_length=255, null=True, blank=True)
    name = models.CharField(max_length=255)
    description = models.TextField(null=True, blank=True)

    class Meta:
        app_label = 'misago'

    def get_extra(self):
        return pickle.loads(base64.decodestring(self.extra))

    @property
    def value(self):
        if self.normalize_to == 'array':
            return self._value.split(',')
        if self.normalize_to == 'integer':
            return int(self._value)
        if self.normalize_to == 'float':
            return float(self._value)
        if self.normalize_to == 'boolean':
            return self._value == "1"
        return self._value

    @value.setter
    def value(self, value):
        if self.normalize_to == 'array':
            self._value = ','.join(value)
        elif self.normalize_to == 'integer':
            self._value = int(value)
        elif self.normalize_to == 'float':
            self._value = float(value)
        elif self.normalize_to == 'boolean':
            self._value = 1 if value else 0
        else:
            self._value = value
        if not self._value and self.value_default:
            self._value = self.value_default
        return self._value

    def get_field(self):
        from misago.forms import YesNoSwitch

        extra = self.get_extra()

        # Set validators
        field_validators = []
        if 'min' in extra:
            if self.normalize_to in ('string', 'array'):
                field_validators.append(validators.MinLengthValidator(extra['min']))
            if self.normalize_to in ('integer', 'float'):
                field_validators.append(validators.MinValueValidator(extra['min']))
        if 'max' in extra:
            if self.normalize_to in ('string', 'array'):
                field_validators.append(validators.MaxLengthValidator(extra['max']))
            if self.normalize_to in ('integer', 'float'):
                field_validators.append(validators.MaxValueValidator(extra['max']))

        # Yes-no
        if self.field == 'yesno':
            return forms.BooleanField(
                                   initial=self.value,
                                   label=_(self.name),
                                   help_text=_(self.description) if self.description else None,
                                   required=False,
                                   widget=YesNoSwitch,
                                   )

        # Multi-list
        if self.field == 'mlist':
            return forms.MultipleChoiceField(
                                     initial=self.value,
                                     label=_(self.name),
                                     help_text=_(self.description) if self.description else None,
                                     widget=forms.CheckboxSelectMultiple,
                                     validators=field_validators,
                                     required=False,
                                     choices=extra['choices']
                                     )

        # Select or choice
        if self.field == 'select' or self.field == 'choice':
            # Timezone list?
            if extra['choices'] == '#TZ#':
                extra['choices'] = tzlist()
            return forms.ChoiceField(
                                     initial=self.value,
                                     label=_(self.name),
                                     help_text=_(self.description) if self.description else None,
                                     widget=forms.RadioSelect if self.field == 'choice' else forms.Select,
                                     validators=field_validators,
                                     required=False,
                                     choices=extra['choices']
                                     )

        # Textarea
        if self.field == 'textarea':
            return forms.CharField(
                                   initial=self.value,
                                   label=_(self.name),
                                   help_text=_(self.description) if self.description else None,
                                   validators=field_validators,
                                   required=False,
                                   widget=forms.Textarea
                                   )

        kwargs = {
                  'initial': self.value,
                  'label': _(self.name),
                  'help_text': _(self.description) if self.description else None,
                  'validators': field_validators,
                  'required': False,
                 }

        # Default input
        default_input = forms.CharField
        if self.normalize_to == 'integer':
            default_input = forms.IntegerField

        if self.normalize_to == 'float':
            default_input = forms.FloatField

        # Make text-input
        return default_input(**kwargs)
