from django import forms
from django.conf import settings
from django.core.exceptions import ValidationError
from django.core.validators import RegexValidator
from django.utils.translation import ugettext_lazy as _
from django.contrib.auth import get_user_model
from registration.forms import validators
from captcha.fields import CaptchaField
from ldapregister.forms import RegistrationForm
from purist.models import get_woo_connection
import strictyaml


User = get_user_model()


def validate_reserved_names(value):
    # premature optimization is the root of all evil
    for bad_word in settings.REG_BAD_SUBSTRINGS:
        if bad_word in value:
            raise ValidationError(validators.RESERVED_NAME, code='invalid')


def woo_email_available_validator(value):
    wc = get_woo_connection()
    result = wc.get('customers?email={}'.format(value))
    if result.ok and len(result.json()) > 0:
        raise ValidationError(_('This recovery email is already in use.'))


def get_reg_options():

    with open(settings.WOO_REG_OPTIONS_INFO_FILE, 'r') as stream:
        return strictyaml.load(stream.read()).data


class CartRegistrationForm(RegistrationForm):
    class Meta(RegistrationForm.Meta):
        fields = (
            User.USERNAME_FIELD,
            'password1',
            'password2',
            'email',
        )

    field_order = ('username', 'email', 'password1', 'password2',
                   'bundle_choice', 'period_choice', 'description', 'captcha')

    email = forms.EmailField(
        label=_('Recovery email address'),
        help_text=_('Enter an email address where we can send you '
                    'recovery information.'),
        validators=[
            validators.validate_confusables_email,
            woo_email_available_validator
        ],
    )

    password1 = forms.CharField(
        label=_("Passphrase"),
        strip=False,
        widget=forms.PasswordInput,
        help_text=_('A good passphrase is made of at least three long words.'),
        validators=[
            RegexValidator(
                regex=r'[\\\'\"]',
                message=_('\\ \' and \" are not valid characters'),
                code=None,
                inverse_match=True,
                flags=0),
        ],
    )

    def __init__(self, layout=None, *args, **kwargs):
        super(CartRegistrationForm, self).__init__(*args, **kwargs)
        self.fields['username'].validators.append(validate_reserved_names)
        self.reg_options = get_reg_options()
        bundles = list(self.reg_options.keys())
        periods = list(self.reg_options[bundles[0]].keys())

        full_bundle = forms.ChoiceField(
            label=_('Bundle type'),
            widget=forms.RadioSelect(attrs={'onclick': 'update_desc()'}),
            choices=list(zip(bundles, bundles))
        )
        full_period = forms.ChoiceField(
            label=_('Billing period'),
            widget=forms.RadioSelect(attrs={'onclick': 'update_desc()'}),
            choices=list(zip(periods, periods))
        )
        hidden_bundle = forms.CharField(
            label=_('Bundle type'),
            widget=forms.HiddenInput,
        )
        hidden_period = forms.CharField(
            label=_('Billing period'),
            widget=forms.HiddenInput,
        )

        # Basic monthly
        if layout == bundles[0].lower():

            hidden_bundle.initial = bundles[0]
            hidden_period.initial = periods[0]
            self.fields['bundle_choice'] = hidden_bundle
            self.fields['period_choice'] = hidden_period

        # Complete filter: bundle is hidden and user can choose period
        elif layout == bundles[1].lower():

            hidden_bundle.initial = bundles[1]
            self.fields['bundle_choice'] = hidden_bundle
            self.fields['period_choice'] = full_period

        # Complete monthly
        elif layout == (bundles[1] + '_' + periods[0]).lower():

            hidden_bundle.initial = bundles[1]
            hidden_period.initial = periods[0]
            self.fields['bundle_choice'] = hidden_bundle
            self.fields['period_choice'] = hidden_period

        # Complete annual
        elif layout == (bundles[1] + '_' + periods[1]).lower():

            hidden_bundle.initial = bundles[1]
            hidden_period.initial = periods[1]
            self.fields['bundle_choice'] = hidden_bundle
            self.fields['period_choice'] = hidden_period

        # Family filter: bundle is hidden and user can choose period
        elif layout == bundles[2].lower():

            hidden_bundle.initial = bundles[2]
            self.fields['bundle_choice'] = hidden_bundle
            self.fields['period_choice'] = full_period

        # Family monthly
        elif layout == (bundles[2] + '_' + periods[0]).lower():

            hidden_bundle.initial = bundles[2]
            hidden_period.initial = periods[0]
            self.fields['bundle_choice'] = hidden_bundle
            self.fields['period_choice'] = hidden_period

        # Family annual
        elif layout == (bundles[2] + '_' + periods[1]).lower():

            hidden_bundle.initial = bundles[2]
            hidden_period.initial = periods[1]
            self.fields['bundle_choice'] = hidden_bundle
            self.fields['period_choice'] = hidden_period

        # Form used by invitation registration: No extra fields added
        elif layout == 'Invitee':
            pass

        # No known layout specified: All options shown to the user
        else:

            self.fields['bundle_choice'] = full_bundle
            self.fields['period_choice'] = full_period
            self.fields['description'] = forms.CharField(
                label='', disabled=True, initial='', required=False)

        self.order_fields(self.field_order)

    def clean_email(self):
        return self.cleaned_data['email'].lower()

    def clean(self):
        super(CartRegistrationForm, self).clean()
        bundle_choice = self.cleaned_data.get('bundle_choice', None)
        period_choice = self.cleaned_data.get('period_choice', None)
        if bundle_choice == 'Basic' and period_choice == 'Annual':
            raise forms.ValidationError(
                _('Basic Annual is not a valid combination.')
            )


class CartRegistrationFormWithCaptcha(CartRegistrationForm):
    captcha = CaptchaField(
        label=_('Please solve this math problem'),
        help_text=_('Prove you are not a robot. Solve this addition, '
                    'subtraction or multiplication problem.'),
    )
