from django import forms
from django.forms.utils import ValidationError

from .validators import validate_email_nouser
from .models import Subscriber


class SubscribeForm(forms.ModelForm):

    class Meta:
        model = Subscriber
        fields = ['user']


class NewsletterForm(forms.ModelForm):
    """ This is the base class for all forms managing subscriptions. """
    email_field = forms.EmailField(label='Email Address:', widget=forms.EmailInput(attrs={'placeholder': 'Your email address'}))

    class Meta:
        model = Subscriber
        fields = ('email_field',)

    def __init__(self, *args, **kwargs):

        assert 'newsletter' in kwargs, 'No newsletter specified'

        newsletter = kwargs.pop('newsletter')

        if 'ip' in kwargs:
            ip = kwargs['ip']
            del kwargs['ip']
        else:
            ip = None

        super(NewsletterForm, self).__init__(*args, **kwargs)

        self.instance.newsletter = newsletter

        if ip:
            self.instance.ip = ip


class SubscribeRequestForm(NewsletterForm):
    """
    Request subscription to the newsletter. Will result in an activation email
    being sent with a link where one can edit, confirm and activate one's
    subscription.
    """
    email_field = forms.EmailField(
        label=("e-mail"), validators=[validate_email_nouser], widget=forms.EmailInput(attrs={'placeholder': 'Your email address'})
    )

    def clean_email_field(self):
        data = self.cleaned_data['email_field']

        # Check whether we have already been subscribed to
        try:
            subscription = Subscriber.objects.get(
                email_field__exact=data,
                newsletter=self.instance.newsletter
            )

            if subscription.subscribed and not subscription.unsubscribed:
                raise ValidationError(
                    "Your e-mail address has already been subscribed to."
                )
            else:
                self.instance = subscription

            self.instance = subscription

        except Subscriber.DoesNotExist:
            pass

        return data


class UpdateForm(NewsletterForm):
    """
    This form allows one to actually update to or unsubscribe from the
    newsletter. To do this, a correct activation code is required.
    """

    email_field = forms.EmailField(
        label=("e-mail"), validators=[validate_email_nouser], disabled=True
    )

    def clean_user_activation_code(self):
        data = self.cleaned_data['user_activation_code']

        if data != self.instance.activation_code:
            raise ValidationError(
                ('The validation code supplied by you does not match.')
            )

        return data

    user_activation_code = forms.CharField(
        label=("Activation code"), max_length=40
    )