"""
Created on 08.05.2011

@author: christian
"""
import re

from django.conf import settings
from django.core import validators
from django.core.validators import EMPTY_VALUES
from django.forms import utils, Form, ModelForm, ValidationError
import django.forms.fields
from django.utils.translation import gettext as _

from . import widgets


class Html5Mixin(object):
    def widget_attrs(self, widget):
        """
        Overwrites the standard Widget Attributes to add some HTML5 Stuff
        :param widget: A Widget Object
        """
        attrs = super(Html5Mixin, self).widget_attrs(widget)
        if self.required and not isinstance(widget, widgets.CheckboxInput):
            attrs['required'] = 'required'
        if self.help_text:
            attrs['title'] = self.help_text
            attrs['placeholder'] = self.help_text
        if self.accesskey:
            attrs['accesskey'] = self.accesskey
        return attrs

    def __init__(self, *args, **kwargs):
        self.accesskey = kwargs.pop('accesskey', None)
        super(Html5Mixin, self).__init__(*args, **kwargs)


class AutoCompleteSelectField(Html5Mixin, django.forms.Field):
    widget = widgets.AutoCompleteSelectWidget
    default_error_messages = {
        'invalid_choice': _(u'Select a valid choice. That choice is not one \
        of the available choices.'),
    }

    def __init__(self, lookup_class, *args, **kwargs):
        self.lookup_class = lookup_class
        self.allow_new = kwargs.pop('allow_new', False)
        if not kwargs['widget']:
            kwargs['widget'] = self.widget(lookup_class,
                                           allow_new=self.allow_new)
        super(AutoCompleteSelectField, self).__init__(*args, **kwargs)

    def to_python(self, value):
        if value in EMPTY_VALUES:
            return None
        if isinstance(value, list):
            # Input comes from an AutoComplete widget. It's two
            # components: text and id
            if len(value) != 2:
                raise django.forms.ValidationError(
                    self.error_messages['invalid_choice'])
            lookup = self.lookup_class()
            if value[1] in EMPTY_VALUES:
                if not self.allow_new:
                    if value[0]:
                        raise django.forms.ValidationError(
                            self.error_messages['invalid_choice'])
                    else:
                        return None
                value = lookup.create_item(value[0])
            else:
                value = lookup.get_item(value[1])
                if value is None:
                    raise django.forms.ValidationError(
                        self.error_messages['invalid_choice'])
        return value


class AutoComboboxSelectField(AutoCompleteSelectField):
    widget = widgets.AutoComboboxSelectWidget


class AutoCompleteSelectMultipleField(Html5Mixin, django.forms.Field):
    widget = widgets.AutoCompleteSelectMultipleWidget

    default_error_messages = {
        'invalid_choice': _(u'Select a valid choice. \
        That choice is not one of the available choices.'),
    }

    def __init__(self, lookup_class, *args, **kwargs):
        self.lookup_class = lookup_class
        kwargs['widget'] = self.widget(lookup_class)
        self.attrs['autofocus'] = 'autofocus'
        super(AutoCompleteSelectMultipleField, self).__init__(*args, **kwargs)

    def to_python(self, value):
        if value in EMPTY_VALUES:
            return None
        lookup = self.lookup_class()
        items = []
        for v in value:
            if v not in EMPTY_VALUES:
                item = lookup.get_item(v)
                if item is None:
                    raise django.forms.ValidationError(
                        self.error_messages['invalid_choice'])
                items.append(item)
        return items


class AutoComboboxSelectMultipleField(AutoCompleteSelectMultipleField):
    widget = widgets.AutoComboboxSelectMultipleWidget


class BooleanField(Html5Mixin, django.forms.BooleanField):
    widget = widgets.CheckboxInput


class CharField(Html5Mixin, django.forms.CharField):
    pass


class DateField(Html5Mixin, django.forms.fields.DateField):
    widget = widgets.DateInput


class DateTimeField(Html5Mixin, django.forms.fields.DateTimeField):
    widget = widgets.DateTimeInput


class EmailField(Html5Mixin, django.forms.fields.EmailField):
    widget = widgets.EmailInput


class FileField(Html5Mixin, django.forms.fields.FileField):
    widget = widgets.NumberInput
    pass


class FloatField(Html5Mixin, django.forms.fields.FloatField):
    pass


class HiddenInput(Html5Mixin, django.forms.HiddenInput):
    pass


class IntegerField(Html5Mixin, django.forms.fields.IntegerField):
    widget = widgets.NumberInput

    def widget_attrs(self, widget):
        attrs = super(IntegerField, self).widget_attrs(widget)
        if isinstance(widget, widgets.NumberInput):
            if self.min_value is not None:
                attrs['min'] = self.min_value
            if self.max_value is not None:
                attrs['max'] = self.max_value
        return attrs


class ModelChoiceField(Html5Mixin, django.forms.ModelChoiceField):
    pass


class PasswordInput(Html5Mixin, django.forms.PasswordInput):
    pass


class PhoneField(Html5Mixin, django.forms.CharField):
    widget = widgets.PhoneInput

    def __init__(self, regex=None, max_length=None, min_length=None,
                 error_message=None, *args, **kwargs):
        super(PhoneField, self).__init__(max_length, min_length,
                                         *args, **kwargs)
        self._set_regex(u'^[0-9+-/ ]+$')

    def _get_regex(self):
        return self._regex

    def _set_regex(self, regex=u'^[0-9+-/ ]+$'):
        regex = re.compile(regex, re.UNICODE)
        self._regex = regex
        if hasattr(self, '_regex_validator') \
                and self._regex_validator in self.validators:
            self.validators.remove(self._regex_validator)
        self._regex_validator = validators.RegexValidator(regex=regex)
        self.validators.append(self._regex_validator)

    regex = property(_get_regex, _set_regex)


class ReCaptchaField(django.forms.fields.CharField):
    def __init__(self, *args, **kwargs):
        self.widget = widgets.ReCaptchaInput
        self.required = True
        super(ReCaptchaField, self).__init__(*args, **kwargs)

    def _check_recaptcha(self, challenge_value, response_value, remote_ip=None):
        """
        Submits a reCAPTCHA request for verification.
        Returns RecaptchaResponse for the request

        @param challenge_value: value of recaptcha_challenge_field
        @param response_value: value of recaptcha_response_field
        @param remoteip -- the user's ip address

        """
        import urllib
        import urllib2

        private_key = settings.RECAPTCHA_PRIVATE_KEY
        challenge_value = challenge_value.encode('utf-8')
        response_value = response_value.encode('utf-8')
        params = urllib.urlencode({
            'privatekey': private_key,
            'remoteip': remote_ip,
            'challenge': challenge_value,
            'response': response_value,
        })

        request = urllib2.Request(
            url="http://www.google.com/recaptcha/api/verify",
            data=params,
            headers={
                "Content-type": "application/x-www-form-urlencoded",
                "User-agent": "reCAPTCHA Python"
            }
        )
        httpresp = urllib2.urlopen(request)

        return_values = httpresp.read().splitlines()
        httpresp.close()

        return_code = return_values[0]
        if (return_code == "true"):
            return True
        else:
            return False

    def clean(self, values):
        challenge_value = values[0]
        response_value = values[1]
        super(ReCaptchaField, self).clean(response_value)
        if not challenge_value:
            raise ValidationError(
                _(u'The CAPTCHA challenge is missing.'))
        elif not response_value:
            raise ValidationError(
                _(u'The CAPTCHA solution is missing.'))
        elif self._check_recaptcha(challenge_value, response_value):
            return challenge_value
        else:
            raise ValidationError(
                _(u'The CAPTCHA solution was incorrect.'))


class RegexField(Html5Mixin, django.forms.RegexField):
    pass


class SlugField(Html5Mixin, django.forms.SlugField):
    pass


class URLField(Html5Mixin, django.forms.fields.URLField):
    widget = widgets.URLInput
