"""
Created on 03.10.2011

@author: Christian
"""

from captcha.fields import ReCaptchaField
from django import forms
from django.conf import settings
from django.contrib import auth
from django.contrib.sites.models import Site
from django.utils.translation import ugettext_lazy as _

from utils.massmailer import MassMailer
from . import models


class MembershipForm(forms.ModelForm):
    """Form for users to change their own user data."""
    error_css_class = 'error'
    required_css_class = 'required'
    birthday = forms.DateField(
        label=_('birthday'),
        required=False,
        help_text=_('Input format: yyyy-mm-dd')
    )
    email = forms.EmailField(label=_('Email'), required=True)

    class Meta:
        """get the user model dyamicly"""
        model = auth.get_user_model()
        fields = (
            'username', 'gender', 'first_name', 'last_name', 'email', 'avatar',
            'website', 'membership', 'birthday', 'telephone', 'street_name',
            'post_code', 'city'
        )

    def clean_birthday(self):
        """If the user wants to be a member the birthday field is mandatory."""
        if self.cleaned_data['membership'] \
                and not self.cleaned_data['birthday']:
            raise forms.ValidationError(_('For your membership, we need this. \
            Please fill out this field yet.'))
        return self.cleaned_data['birthday']

    def clean_street_name(self):
        """If the user wants to be a member the address is mandatory."""
        if self.cleaned_data['membership'] \
                and not self.cleaned_data['street_name']:
            raise forms.ValidationError(_('For your membership, we need this. \
            Please fill out this field yet.'))
        return self.cleaned_data['street_name']

    def clean_post_code(self):
        """If the user wants to be a member the address is mandatory."""
        if self.cleaned_data['membership'] \
                and not self.cleaned_data['post_code']:
            raise forms.ValidationError(_('For your membership, we need this. \
            Please fill out this field yet.'))
        return self.cleaned_data['post_code']

    def clean_city(self):
        """If the user wants to be a member the address is mandatory."""
        if self.cleaned_data['membership'] and not self.cleaned_data['city']:
            raise forms.ValidationError(_('For your membership, we need this. \
             Please fill out this field yet.'))
        return self.cleaned_data['city']


class RegistrationForm(MembershipForm):
    """Form to register a new user account.

    Validates that the requested username and email is not already in use,
    requires the password to be entered twice to catch typos.
    Also sends an activation request per mail, to validate the email.
    """
    password1 = forms.CharField(
        widget=forms.PasswordInput(), label=_('password'))
    password2 = forms.CharField(
        widget=forms.PasswordInput(), label=_('password (again)'))
    recaptcha = ReCaptchaField()

    class Meta:
        """Metadata to localize and customize the ModelForm."""
        model = auth.get_user_model()
        fields = ('first_name', 'last_name', 'username', 'email',
                  'username', 'gender', 'first_name', 'last_name', 'email',
                  'avatar',
                  'website', 'membership', 'birthday', 'telephone',
                  'street_name',
                  'post_code', 'city'
                  )

    def clean_username(self):
        """Validate that the username is not already in use."""
        try:
            auth.get_user_model().objects.get(
                username__iexact=self.cleaned_data['username']
            )
        except auth.get_user_model().DoesNotExist:
            return self.cleaned_data['username']
        raise forms.ValidationError(_(u'This username is already taken. \
        Please choose another.'))

    def clean_email(self):
        """Validate that the supplied email address is unique for the site."""
        if auth.get_user_model().objects.filter(
                email__iexact=self.cleaned_data['email']):
            raise forms.ValidationError(_(u'This email address is already in \
            use. Please supply a different email address.'))
        return self.cleaned_data['email']

    def clean_password2(self):
        """Check that the password has been entered identical for two times."""
        password1 = self.cleaned_data.get("password1", "")
        password2 = self.cleaned_data["password2"]
        if password1 != password2:
            raise forms.ValidationError(
                _("The two password fields didn't match."))
        return password2

    def save(self, commit=True):
        """ Create the new User, set him/her inactive, create an acitivation
        request for the user and send him/her an activation email.
        
        :param commit: commit the SQL and send the email if True
        :return: the created User Object
        """
        user = super(RegistrationForm, self).save(commit=False)
        user.set_password(self.cleaned_data["password1"])
        user.is_active = False
        if commit:
            user.save()
            activation_request = models.ActivationRequest.objects \
                .create_pending_registration(user)
            mailer = MassMailer(
                subject='Deine Anmeldung auf %s' % Site.objects.get_current(),
                txt_template='membership/email/activation_email.txt',
                context={
                    'user': activation_request.user,
                    'site': Site.objects.get_current(),
                    'activation_key': activation_request.activation_key,
                    'expiration_days': settings.ACCOUNT_ACTIVATION_DAYS,
                }
            )
            mailer.send(recipients=[activation_request.user])
        return user
