"""
Created on 03.10.2011

@author: Christian
"""
from datetime import date
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 gettext_lazy as _
from utils.massmailer import MassMailer
from . import models
from content.models import Page


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)
    required_membership_fields = ('first_name', 'last_name', 'birthday')

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

    def clean(self):
        cleaned_data = super().clean()
        errormsg = _('For your membership, we need this. \
            Please fill out this field yet.')
        membership = cleaned_data.get('membership')
        for fieldname in self.required_membership_fields:
            if membership and not cleaned_data.get(fieldname):
                self.add_error(fieldname, errormsg)
        if membership and cleaned_data.get('birthday'):
            birthday = cleaned_data.get('birthday')
            today = date.today()
            age = today.year - birthday.year - (
                    (today.month, today.day) < (birthday.month, birthday.day))
            if age < 16:
                self.add_error('birthday',
                               'Midestalter für Mitlieder ist 16 Jahre!')


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)'))
    privacy_policy = forms.BooleanField(
        label=_('Privacy policy'),
        help_text=_(
            'I have read and understood the <a href="%s">privacy policy</a>') %
        Page.objects.get(slug='privacypolicy').get_absolute_url())
    membership = forms.BooleanField(
        label=_('Membership'),
        help_text=_(
            'Yes, I confirm that I am in agreement with the '
            '<a href="%s">statutes</a> and would like to become a member.') %
        Page.objects.get(slug='statutes').get_absolute_url())

    recaptcha = ReCaptchaField()

    class Meta:
        """Metadata to localize and customize the ModelForm."""
        model = auth.get_user_model()
        fields = ('first_name', 'last_name', 'username', 'email',
                  'avatar',
                  '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
