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

from urlparse import urljoin

from django.utils.translation import ugettext_lazy as _
from django.shortcuts import redirect
from django.views.generic.edit import FormView
from django.views.generic import TemplateView
from django.utils.http import urlencode
from django.conf import settings
from django.contrib.auth import logout, login
from django.contrib import messages
from django.core.urlresolvers import reverse
from django.db.models import Q

import forms
import models
from utils import next_url

class VueFormulaireAvecRelaie(FormView):
    static_next_url = None

    def get_success_url(self):
        return next_url(self.request, self.static_next_url)

    def get_form_kwargs(self, **kwargs):
        kwargs = super(VueFormulaireAvecRelaie, self).get_form_kwargs(**kwargs)
        kwargs['request'] = self.request
        return kwargs

    def get_context_data(self, **kwargs):
        ctx = super(VueFormulaireAvecRelaie, self).get_context_data(**kwargs)
        ctx['next'] = self.get_success_url()
        return ctx

def is_webmaster(user):
    return user.has_perm('fiber.change_page')

class Validation(object):
    '''Mixin permettant de limiter une vue aux seuls utilisateurs validant une certain condition'''

    def dispatch(self, request, *args, **kwargs):
        self.request = request
        user = request.user
        if not is_webmaster(user):
            for validateur, url in self.validateurs:
                if not validateur(self, user):
                    url = '%s?%s' % (url,
                        urlencode({'next': request.get_full_path()}))
                    request.record('acces-interdit',
                            _(u'utilisateur invalide sur {url}, redirection'
                              u' vers {redirect}'), url=request.path,
                                redirect=url)
                    return redirect(url)
        return super(Validation, self).dispatch(request, *args, **kwargs)

class ValidationCGU(Validation):
    '''
       Limite une vue aux utilisateurs ayant validé les condition générales
       d'utilisation.

       Dans le cas contraire ils sont redirigés sur la page de validation des
       CGU.
    '''
    def valider_cgu(self, user):
        return getattr(user, 'acceptation_cgu', False)

    validateurs = ((valider_cgu, '/acceptation-cgu/'),)

class ValidationCharteQualite(ValidationCGU):
    '''
       Limite une vue aux utilisateurs ayant validé la charte qualité.

       Dans le cas contraire ils sont redirigés sur la page de validation de la
       charte qualité.
    '''
    def valider_charte_qualite(self, user):
        return getattr(user, 'acceptation_charte_qualite', False)

    validateurs = ValidationCGU.validateurs + ((valider_charte_qualite,
        '/acceptation-charte-qualite/'),)

class CGUCharteQualiteEtPossederMotDePasse(ValidationCharteQualite):
    def valider_posseder_mot_de_passe(self, user):
        if not user.has_usable_password():
            messages.info(self.request, _(u"Pour finir votre inscription veuillez"
                u" choisir un mot de passe"))
            return False
        return True

    validateurs = ValidationCharteQualite.validateurs + \
            ((valider_posseder_mot_de_passe, '/changement-mot-de-passe/'),)

class SeulementPourProfil(object):
    '''
       Vue générique permettant de limiter l'accès à une vue à certains
       profils.

       Dans le cas où ils ne seraient pas du bon profil qu'ils ne soit pas
       connectés, ils sont renvoyés sur une page de login défini par
       l'attribute ``login_url``.

       L'attribut ``profil`` est une séquence de classes de profil.
    '''
    profil = []
    login_url = '/login'

    def dispatch(self, request, *args, **kwargs):
        if not is_webmaster(request.user) and not isinstance(request.user, self.profil):
            url = '%s?%s' % (self.login_url,
                urlencode({'next': request.get_full_path()}))
            request.record('acces-interdit', _(u'impossible d\'afficher la vue '
                u'{url}, elle est réservé au(x) profil(s) {profil}, '
                u'redirection sur {redirect}'),
                    url=request.path, profil=self.profil, redirect=self.login_url)
            return redirect(url)
        return super(SeulementPourProfil, self).dispatch(request, *args, **kwargs)


class VueRelaieMixin(object):
    static_next_url = None

    def next_url(self):
        return next_url(self.request, self.static_next_url)

class AcceptationVue(FormView, VueRelaieMixin):
    '''Vue spécialisée dans l'affichage d'un formulaire visant à valider un
       certain paramètre du profil.
    '''

    def post(self, request, *args, **kwargs):
        if 'refuse' in request.POST:
            return redirect('/')
        return super(AcceptationVue, self).post(request, *args, **kwargs)

    def get_success_url(self):
        return self.next_url()

    def modify_user(self, user):
        '''Méthode à surcharger pour effectuer la modification du profil de l'utilisateur'''
        pass

    def form_valid(self, form):
        self.modify_user(self.request.user)
        return super(AcceptationVue, self).form_valid(form)

    class Media:
        css = { 'all': ('bootstrap/css/bootstrap.css',) }
        js = ('fiber/js/jquery-1.5.2.min.js', 'bootstrap/js/bootstrap.min.js')

class AcceptationCGU(AcceptationVue):
    form_class = forms.AcceptationCguForm
    template_name = 'appli_socle/acceptation-cgu.html'

    def modify_user(self, user):
        user.acceptation_cgu = True
        user.save()
        self.request.record('validation-cgu', _(u'validation des CGU'))

class AcceptationCharteQualite(AcceptationVue):
    form_class = forms.AcceptationCharteQualiteForm
    template_name = 'appli_socle/acceptation-cgu.html'

    def modify_user(self, user):
        user.acceptation_charte_qualite = True
        user.save()
        self.request.record('validation-charte-qualite', _(u'validation de la charte qualité'))

class Deconnexion(TemplateView):
    '''Vue de déconnexion'''
    template_name = 'appli_socle/deconnexion.html'

    def get(self, request, *args, **kwargs):
        result = super(Deconnexion, self).get(request, *args, **kwargs)
        if request.user.is_authenticated():
            request.record('deconnexion', _(u'deconnexion'))
            logout(request)
        return result

    def get_context_data(self, **kwargs):
        context = super(Deconnexion, self).get_context_data(**kwargs)
        user = self.request.user
        if not user.is_anonymous() and not user.has_usable_password():
            context['cas_logout_url'] = urljoin(settings.CAS_URL, 'logout')
        return context

class Homepage(TemplateView):
    template_name = 'homepage.html'

    def get_context_data(self, **kwargs):
        context = super(Homepage, self).get_context_data(**kwargs)
        context['form_etudiant'] = forms.AuthentificationEntHomepageForm()
        context['form_proprio'] = forms.AuthentificationHomepageForm()
        context['annonces'] = models.Annonce.objects \
                .filter(Q(nos_logements=True)|Q(etat_validation='publiee')) \
                .order_by('nos_logements', '-derniere_validation')[:3]

        return context

class SupprimerMonCompte(VueRelaieMixin, TemplateView):
    template_name = 'appli_socle/supprimer-mon-compte.html'
    static_next_url = '/'

    def dispatch(self, request, *args, **kwargs):
        self.request = request
        user = request.user
        if isinstance(user, models.ProfilRecherche):
            self.user_type = 'recherche'
            if bool(user.utilisateur_cas.all()):
                self.user_type = 'ent'
        elif isinstance(user, models.ProfilOffre):
            self.user_type = 'offre'
        else:
            return redirect(self.next_url())
        return super(SupprimerMonCompte, self).dispatch(request, *args, **kwargs)

    def get_context_data(self, **kwargs):
        context = super(SupprimerMonCompte, self).get_context_data(**kwargs)
        context['next'] = next_url(self.request, '/')
        context['type'] = self.user_type
        return context

    def post(self, request, *args, **kwargs):
        if 'confirmer' in request.POST:
            user = request.user
            request.record('supprime-compte', 'suppression du compte {user}', user=user)
            logout(request)
            user.delete()
            messages.info(self.request,
                    _(u'Votre compte %s a été supprimé') % user.email)
        return redirect(self.next_url())

class VueCodeDeConfirmationEmail(FormView):
    '''
       Formulaire de confirmation des emails, sert à l'inscription, changement
       d'email, récupération du mot de passe.
    '''
    form_class = forms.CodeDeConfirmationForm
    template_name = 'appli_socle/code-de-confirmation.html'

    def get_form_kwargs(self, **kwargs):
        kwargs = super(VueCodeDeConfirmationEmail, self).get_form_kwargs(**kwargs)
        initial = kwargs.setdefault('initial', dict())
        initial['jeton'] = self.kwargs.get('jeton', '')
        return kwargs

    def form_valid(self, form):
        login(self.request, form.user_cache)
        form.save()
        self.request.record('confirmation-email',
                _(u'confirmation de l\'email {email} avec le jeton {jeton}'),
                email=form.value['email'],
                jeton=form.cleaned_data['jeton'])
        if getattr(form, 'created', False):
            self.request.record('nouveau-compte-offre',
                    _(u'création du compte {email}'),
                    email=form.value['email'])
            self.request.record('connexion', _(u'première connexion'), first='1')
        else:
            self.request.record('connexion', _(u'connexion automatique après récupération du mot de passe'))
        self.success_url = form.next_url
        return super(VueCodeDeConfirmationEmail, self).form_valid(form)

class VueMotDePassePerdu(FormView):
    form_class = forms.MotDePassePerduForm
    template_name = 'forms.html'

    def get_form_kwargs(self, **kwargs):
        kwargs = super(VueMotDePassePerdu, self).get_form_kwargs(**kwargs)
        kwargs['request'] = self.request
        kwargs['initial'] = { 'email': self.kwargs['email'] }
        return kwargs

    def form_valid(self, form):
        self.request.record('recuperation-mot-de-passe',
                _(u'demande de récupération de mot de passe pour l\'email {email}'),
                email=form.cleaned_data['email'])
        for user, jeton in form.save():
            self.request.record('recuperation-mot-de-passe',
                _(u'mail de récupération de mot de passe envoyé à {email} avec '
                  u'le jeton {jeton}'),
                    email=user.email, jeton=jeton)
        messages.info(self.request, _(u'''Un code de confirmation vous a été envoyé'''
            u''' par mail. Il vous permettra de récupérer votre mot'''
            u''' de passe en le copiant sur le site.'''))
        return super(VueMotDePassePerdu, self).form_valid(form)

    def get_success_url(self):
        return reverse('confirmation-email', kwargs=dict(jeton=''))

class ChangementMotDePasse(VueFormulaireAvecRelaie):
    form_class = forms.ChangementMotDePasseForm
    template_name = 'forms.html'

    def form_valid(self, form):
        form.save()
        self.request.record('changement-mot-de-passe', 'changement du mot de passe')
        messages.info(self.request, _(u'''Votre mot de passe a bien été changé.'''))
        return super(ChangementMotDePasse, self).form_valid(form)

    def get_form_kwargs(self, **kwargs):
        kwargs = super(ChangementMotDePasse, self).get_form_kwargs(**kwargs)
        kwargs['user'] = self.request.user
        return kwargs

class PlanDuSite(TemplateView):
    template_name = 'plan-du-site.html'
