# vim:spell:spelllang=fr
# -*- encoding: utf-8 -*-
import datetime

from django.core.exceptions import ValidationError
from django.forms import Form, ModelChoiceField, IntegerField
from django.utils.translation import ugettext_lazy as _
from django.core.exceptions import ValidationError

from models import Parametre

def dict_diff(a, b):
    '''Calcule la différence entre le dictionnaire a et le dictionnaire b'''
    c = {}
    for key in a:
        if key in b:
            if a[key] == b[key]:
                continue
            else:
                c[key] = u'valeur modifiée de %s à %s' % (a[key], b[key])
        else:
            c[key] = u'valeur supprimée %s' % a[key]
    for key in b:
        if key not in a:
            c[key] = u'valeur ajoutée %s' % b[key]
    return c

class FormulaireParametres(Form):
    surface_minimum = IntegerField(label=_(u'Surface minimum pour un logement'),
            help_text=_(u'en m²'), initial=0, min_value=0)
    prix_au_m2_maximum = IntegerField(label=_(u'Prix maximum par m²'),
            help_text=_(u'en € par m²'), initial=0, min_value=0)
    duree_maximum_de_publication = IntegerField(label=_(u'Durée maximum de publication'),
            help_text=_('en jours'), initial=31*3, min_value=0)
    duree_inactivite_profil_offre = IntegerField(
            label=_(u"Durée d'inactivité avant désactivation d'un profil offre"),
            help_text=_('en jours'), initial=6*30, min_value=0)

    def __init__(self, *args, **kwargs):
        kwargs['initial'] = Parametres().as_dict()
        super(FormulaireParametres, self).__init__(*args, **kwargs)

    def check_duree(self, name):
        value = self.cleaned_data[name]
        if value is None:
            raise ValidationError(_(u'Valeur requise'))
        try:
            datetime.date.today()+datetime.timedelta(days=value)
        except OverflowError:
            raise ValidationError(_(u'Valeur trop grande'))
        return value

    def clean_duree_maximum_de_publication(self):
        return self.check_duree('duree_maximum_de_publication')

    def clean_duree_inactivite_profil_offre(self):
        return self.check_duree('duree_inactivite_profil_offre')

    def save_form(self):
        p = Parametres()
        old_p = Parametres()
        for key, value in self.cleaned_data.iteritems():
            setattr(p, key, value)
        return dict_diff(old_p.as_dict(), p.as_dict())

class Parametres(object):
    '''Met en cache la valeur des paramètres et offre une interface d'objet
       Python vers ceux-ci.'''

    def __init__(self, model_class=Parametre):
        self.model_class = Parametre
        self._cache = dict(((p.nom, p) for p in self.model_class.objects.all().select_related()))

    def as_dict(self):
        return dict(((key, getattr(self, key)) for key in FormulaireParametres.base_fields))

    def get_model_field_name(self, field):
        model = field.queryset.model
        for model_field in self.model_class._meta.fields:
            if hasattr(model_field, 'rel') and hasattr(model_field.rel, 'to'):
                if model is model_field.rel.to:
                    break
        else:
            raise ValueError('There is no field in %s class to hold a value for form field %s',
                    self.model_class, field)
        return model_field.name

    def __getattr__(self, nom):
        field = FormulaireParametres.base_fields[nom]
        parametre = self._cache.get(nom)
        if parametre is None:
            return field.clean(field.initial)
        if isinstance(field, ModelChoiceField):
            model_field_name = self.get_model_field_name(field)
            return getattr(parametre, model_field_name)
        else:
            return parametre.valeur

    def __setattr__(self, nom, valeur):
        if nom in ('_cache', 'model_class'):
            return super(Parametres, self).__setattr__(nom, valeur)
        field = FormulaireParametres.base_fields[nom]
        parametre, created = self.model_class.objects.get_or_create(nom=nom)
        if isinstance(field, ModelChoiceField):
            model_field_name = self.get_model_field_name(field)
            setattr(parametre, model_field_name, valeur)
        else:
            parametre.valeur = valeur
        parametre.save()
        self._cache[parametre.nom] = parametre
