"""
Created on 08.05.2011

@author: christian
"""
from django.conf import settings
from django.forms import widgets
from django.forms.utils import flatatt
from django.utils import formats
from django.utils.encoding import force_unicode, force_text
from django.utils.html import conditional_escape
from django.utils.http import urlencode
from django.utils.safestring import mark_safe


class AutoCompleteWidget(widgets.TextInput):
    def __init__(self, lookup_class, attrs=None, *args, **kwargs):
        self.lookup_class = lookup_class
        self.allow_new = kwargs.pop('allow_new', False)
        self.qs = {}
        super(AutoCompleteWidget, self).__init__(*args, **kwargs)
        if attrs is not None:
            self.attrs = attrs.copy()
        else:
            self.attrs = {}

    def update_query_parameters(self, qs_dict):
        self.qs.update(qs_dict)

    def build_attrs(self, extra_attrs=None, **kwargs):
        attrs = super(AutoCompleteWidget, self).build_attrs(extra_attrs,
                                                            **kwargs)  # @IgnorePep8
        url = self.lookup_class.url()
        if self.qs:
            url = '%s?%s' % (url, urlencode(self.qs))
        attrs[u'data-selectable-url'] = url
        attrs[u'data-selectable-type'] = 'text'
        attrs[u'data-selectable-allow-new'] = str(self.allow_new).lower()
        return attrs


class AutoComboboxWidget(AutoCompleteWidget):
    def build_attrs(self, extra_attrs=None, **kwargs):
        attrs = super(AutoComboboxWidget, self).build_attrs(extra_attrs,
                                                            **kwargs)  # @IgnorePep8
        attrs[u'data-selectable-type'] = 'combobox'
        return attrs


class DateInput(widgets.DateInput):
    input_type = 'date'
    attrs = {'class': 'dateinput'}

    def __init__(self, attrs=None, date_format='%Y-%m-%d'):
        super(DateInput, self).__init__(attrs)
        if date_format:
            self.format = date_format
            self.manual_format = True
        else:
            self.format = formats.get_format('DATE_INPUT_FORMATS')[0]
            self.manual_format = False


class DateTimeInput(widgets.MultiWidget):
    """
    A Widget that splits datetime input into two <input type="text"> boxes.
    """

    def __init__(self, attrs=None, date_format='%Y-%m-%d',
                 time_format='%H:%M'):  # @IgnorePep8
        widgets = (
            DateInput(attrs=attrs, date_format=date_format),
            TimeInput(attrs=attrs, time_format=time_format)
        )
        super(DateTimeInput, self).__init__(widgets, attrs)

    def decompress(self, value):
        if value:
            return [value.date(), value.time()]
        return [None, None]


class CheckboxInput(widgets.CheckboxInput):
    input_type = 'checkbox'
    is_checkbox = True

    def render(self, name, value, attrs=None):
        final_attrs = self.build_attrs(attrs, type='checkbox', name=name)
        title = force_text(self.attrs.get('title', ''))
        try:
            result = self.check_test(value)
        except:  # Silently catch exceptions
            result = False
        if result:
            final_attrs['checked'] = 'checked'
        if not (
                        value is True or value is False or value is None or value == ''):  # @IgnorePep8
            # Only add the 'value' attribute if a value is non-empty.
            final_attrs['value'] = force_unicode(value)

        return mark_safe(u'<input%s /> %s' % (flatatt(final_attrs), title))


class EmailInput(widgets.TextInput):
    input_type = 'email'


class NumberInput(widgets.TextInput):
    input_type = 'number'

    def __init__(self, attrs=None):
        widgets.Input.__init__(self, attrs=attrs)


class PhoneInput(widgets.TextInput):
    input_type = 'tel'


class RangeInput(widgets.TextInput):
    input_type = 'range'


class ReCaptchaInput(widgets.Widget):
    """
    Der HTML Code von Googles ReCaptcha als Form Widget
    """
    recaptcha_challenge_name = 'recaptcha_challenge_field'
    recaptcha_response_name = 'recaptcha_response_field'

    def render(self, name, value, attrs=None):
        javascript = u"""
        <script type="text/javascript">var RecaptchaOptions = {theme :
        '%(theme)s'};</script><script type="text/javascript"
        src="https://www.google.com/recaptcha/api/challenge?k=%(public_key)s">
        </script><noscript><iframe
        src="https://www.google.com/recaptcha/api/noscript?k=%(public_key)s"
        height="130" width="500"></iframe><br /><textarea
        name="recaptcha_challenge_field" rows="3" cols="40"></textarea><input
        type="hidden" name="recaptcha_response_field" value="manual_challenge">
        </noscript>"""
        return mark_safe(javascript % {'public_key':
                                           settings.RECAPTCHA_PUBLIC_KEY,
                                       'theme': 'red'})

    def value_from_datadict(self, data, files, name):
        return [data.get(self.recaptcha_challenge_name, None),
                data.get(self.recaptcha_response_name, None)]


class SelectableMultiWidget(widgets.MultiWidget):
    def update_query_parameters(self, qs_dict):
        self.widgets[0].update_query_parameters(qs_dict)


class Textarea(widgets.Widget):
    def __init__(self, attrs=None):
        # The 'rows' and 'cols' attributes are required for HTML correctness.
        default_attrs = {'cols': '40', 'rows': '10'}
        if attrs:
            default_attrs.update(attrs)
        super(Textarea, self).__init__(default_attrs)

    def render(self, name, value, attrs=None):
        value = '' if value is None else value
        final_attrs = self.build_attrs(attrs, name=name)
        return mark_safe(u'<textarea%s>%s</textarea>' % (flatatt(final_attrs),
                                                         conditional_escape(
                                                             force_unicode(
                                                                 value))))


class TextInput(widgets.TextInput):
    pass


class TimeInput(widgets.TimeInput):
    input_type = 'time'

    def __init__(self, attrs=None, time_format='%H:%M'):
        default_attrs = {'maxlength': 5, 'size': 5}
        if attrs:
            default_attrs.update(attrs)
        super(TimeInput, self).__init__(default_attrs)

        if time_format:
            self.format = time_format
            self.manual_format = True
        else:
            self.format = formats.get_format('TIME_INPUT_FORMATS')[0]
            self.manual_format = False


class URLInput(widgets.Input):
    input_type = 'url'


class LookupMultipleHiddenInput(widgets.MultipleHiddenInput):
    def __init__(self, lookup_class, *args, **kwargs):
        self.lookup_class = lookup_class
        super(LookupMultipleHiddenInput, self).__init__(*args, **kwargs)

    def render(self, name, value, attrs=None, choices=()):
        lookup = self.lookup_class()
        value = [] if value is None else value
        final_attrs = self.build_attrs(attrs, type=self.input_type, name=name)
        id_ = final_attrs.get('id', None)
        inputs = []
        model = getattr(self.lookup_class, 'model', None)
        for i, v in enumerate(value):
            item = None
            if model and isinstance(v, model):
                item = v
                v = lookup.get_item_id(item)
            input_attrs = dict(value=force_unicode(v), **final_attrs)
            if id_:
                # An ID attribute was given. Add a numeric index as a suffix
                # so that the inputs don't all have the same ID attribute.
                input_attrs['id'] = '%s_%s' % (id_, i)
            if v:
                item = item or lookup.get_item(v)
                input_attrs['title'] = lookup.get_item_value(item)
            inputs.append(u'<input%s />' % flatatt(input_attrs))
        return mark_safe(u'\n'.join(inputs))

    def build_attrs(self, extra_attrs=None, **kwargs):
        attrs = super(LookupMultipleHiddenInput, self).build_attrs(extra_attrs,
                                                                   **kwargs)  # @IgnorePep8
        attrs[u'data-selectable-type'] = 'hidden-multiple'
        return attrs


class AutoCompleteSelectMultipleWidget(SelectableMultiWidget):
    def __init__(self, lookup_class, *args, **kwargs):
        self.lookup_class = lookup_class
        widgets = [
            AutoCompleteWidget(lookup_class, allow_new=False,
                               attrs={u'data-selectable-multiple': 'true'}),
            LookupMultipleHiddenInput(lookup_class)
        ]
        super(AutoCompleteSelectMultipleWidget, self).__init__(widgets, *args,
                                                               **kwargs)  # @IgnorePep8

    def value_from_datadict(self, data, files, name):
        return self.widgets[1].value_from_datadict(data, files, name + '_1')

    def render(self, name, value, attrs=None):
        if value and not hasattr(value, '__iter__'):
            value = [value]
        value = [u'', value]
        return super(AutoCompleteSelectMultipleWidget, self).render(name, value,
                                                                    attrs)  # @IgnorePep8


class AutoComboboxSelectMultipleWidget(SelectableMultiWidget):
    def __init__(self, lookup_class, *args, **kwargs):
        self.lookup_class = lookup_class
        widgets = [
            AutoComboboxWidget(lookup_class, allow_new=False,
                               attrs={u'data-selectable-multiple': 'true'}),
            LookupMultipleHiddenInput(lookup_class)
        ]
        super(AutoComboboxSelectMultipleWidget, self).__init__(widgets, *args,
                                                               **kwargs)  # @IgnorePep8

    def value_from_datadict(self, data, files, name):
        return self.widgets[1].value_from_datadict(data, files, name + '_1')

    def render(self, name, value, attrs=None):
        if value and not hasattr(value, '__iter__'):
            value = [value]
        value = [u'', value]
        return super(AutoComboboxSelectMultipleWidget, self).render(name, value,
                                                                    attrs)  # @IgnorePep8


class AutoCompleteSelectWidget(SelectableMultiWidget):
    def __init__(self, lookup_class, *args, **kwargs):
        self.lookup_class = lookup_class
        self.allow_new = kwargs.pop('allow_new', False)
        widget_set = [
            AutoCompleteWidget(lookup_class, allow_new=self.allow_new),
            widgets.HiddenInput(attrs={u'data-selectable-type': 'hidden'})
        ]
        super(AutoCompleteSelectWidget, self).__init__(widget_set, *args,
                                                       **kwargs)  # @IgnorePep8

    def decompress(self, value):
        if value:
            lookup = self.lookup_class()
            model = getattr(self.lookup_class, 'model', None)
            if model and isinstance(value, model):
                item = value
                value = lookup.get_item_id(item)
            else:
                item = lookup.get_item(value)
            item_value = lookup.get_item_value(item)
            return [item_value, value]
        return [None, None]


class AutoComboboxSelectWidget(SelectableMultiWidget):
    def __init__(self, lookup_class, *args, **kwargs):
        self.lookup_class = lookup_class
        self.allow_new = kwargs.pop('allow_new', False)
        widget_set = [
            AutoComboboxWidget(lookup_class, allow_new=self.allow_new),
            widgets.HiddenInput(attrs={u'data-selectable-type': 'hidden'})
        ]
        super(AutoComboboxSelectWidget, self).__init__(widget_set, *args,
                                                       **kwargs)  # @IgnorePep8

    def decompress(self, value):
        if value:
            lookup = self.lookup_class()
            model = getattr(self.lookup_class, 'model', None)
            if model and isinstance(value, model):
                item = value
                value = lookup.get_item_id(item)
            else:
                item = lookup.get_item(value)
            item_value = lookup.get_item_value(item)
            return [item_value, value]
        return [None, None]
