import datetime

from django import forms
from django.utils import six
from django.utils.translation import ugettext_lazy as _
from django.conf import settings

from .helpers import parse, TimedeltaLocale
from .widgets import TimedeltaWidget


class TimedeltaFormField(forms.Field):
    default_error_messages = {
        'invalid': _('Enter a valid time span: e.g. "3 days, 4 hours, 2 minutes"')
    }

    def __init__(self, *args, **kwargs):
        defaults = {'widget': TimedeltaWidget}
        defaults.update(kwargs)
        super(TimedeltaFormField, self).__init__(*args, **defaults)

    def prepare_value(self, value):
        if value and isinstance(value, datetime.timedelta):
            value = str(TimedeltaLocale(value, language_code=settings.LANGUAGE_CODE))
        return value

    def clean(self, value):
        """
        This doesn't really need to be here: it should be tested in
        parse()...
        
        >>> t = TimedeltaFormField()
        >>> t.clean('1 day')
        datetime.timedelta(1)
        >>> t.clean('1 day, 0:00:00')
        datetime.timedelta(1)
        >>> t.clean('1 day, 8:42:42.342')
        datetime.timedelta(1, 31362, 342000)
        >>> t.clean('3 days, 8:42:42.342161')
        datetime.timedelta(3, 31362, 342161)
        >>> try:
        ...  t.clean('3 days, 8:42:42.3.42161')
        ... except forms.ValidationError as arg:
        ...  six.print_(arg.messages[0])
        Enter a valid time span: e.g. "3 days, 4 hours, 2 minutes"
        >>> t.clean('5 day, 8:42:42')
        datetime.timedelta(5, 31362)
        >>> t.clean('1 days')
        datetime.timedelta(1)
        >>> t.clean('1 second')
        datetime.timedelta(0, 1)
        >>> t.clean('1 sec')
        datetime.timedelta(0, 1)
        >>> t.clean('10 seconds')
        datetime.timedelta(0, 10)
        >>> t.clean('30 seconds')
        datetime.timedelta(0, 30)
        >>> t.clean('1 minute, 30 seconds')
        datetime.timedelta(0, 90)
        >>> t.clean('2.5 minutes')
        datetime.timedelta(0, 150)
        >>> t.clean('2 minutes, 30 seconds')
        datetime.timedelta(0, 150)
        >>> t.clean('.5 hours')
        datetime.timedelta(0, 1800)
        >>> t.clean('30 minutes')
        datetime.timedelta(0, 1800)
        >>> t.clean('1 hour')
        datetime.timedelta(0, 3600)
        >>> t.clean('5.5 hours')
        datetime.timedelta(0, 19800)
        >>> t.clean('1 day, 1 hour, 30 mins')
        datetime.timedelta(1, 5400)
        >>> t.clean('8 min')
        datetime.timedelta(0, 480)
        >>> t.clean('3 days, 12 hours')
        datetime.timedelta(3, 43200)
        >>> t.clean('3.5 day')
        datetime.timedelta(3, 43200)
        >>> t.clean('1 week')
        datetime.timedelta(7)
        >>> t.clean('2 weeks, 2 days')
        datetime.timedelta(16)
        >>> try:
        ...  t.clean(six.u('2 we\xe8k, 2 days'))
        ... except forms.ValidationError as arg:
        ...  six.print_(arg.messages[0])
        Enter a valid time span: e.g. "3 days, 4 hours, 2 minutes"
        """

        super(TimedeltaFormField, self).clean(value)
        if (value == '' or value is None) and not self.required:
            return ''
        try:
            return parse(value, language_code=settings.LANGUAGE_CODE)
        except TypeError:
            raise forms.ValidationError(self.error_messages['invalid'])


class TimedeltaChoicesField(TimedeltaFormField):
    def __init__(self, *args, **kwargs):
        choices = kwargs.pop('choices')
        defaults = {'widget': forms.Select(choices=choices)}
        defaults.update(kwargs)
        super(TimedeltaChoicesField, self).__init__(*args, **defaults)
