from __future__ import absolute_import, unicode_literals

import itertools
import json
from functools import total_ordering

from django.core.urlresolvers import reverse
from django.forms import widgets
from django.forms.utils import flatatt
from django.template.loader import render_to_string
from django.utils.encoding import python_2_unicode_compatible
from django.utils.formats import get_format
from django.utils.html import format_html
from django.utils.translation import ugettext_lazy as _
from taggit.forms import TagWidget

from wagtail.utils.widgets import WidgetWithScript
from wagtail.wagtailcore import hooks
from wagtail.wagtailcore.models import Page


class AdminAutoHeightTextInput(WidgetWithScript, widgets.Textarea):
    def __init__(self, attrs=None):
        # Use more appropriate rows default, given autoheight will alter this anyway
        default_attrs = {'rows': '1'}
        if attrs:
            default_attrs.update(attrs)

        super(AdminAutoHeightTextInput, self).__init__(default_attrs)

    def render_js_init(self, id_, name, value):
        return 'autosize($("#{0}"));'.format(id_)


class AdminDateInput(WidgetWithScript, widgets.DateInput):
    # Set a default date format to match the one that our JS date picker expects -
    # it can still be overridden explicitly, but this way it won't be affected by
    # the DATE_INPUT_FORMATS setting
    def __init__(self, attrs=None, format='%Y-%m-%d'):
        super(AdminDateInput, self).__init__(attrs=attrs, format=format)

    def render_js_init(self, id_, name, value):
        return 'initDateChooser({0}, {1});'.format(
            json.dumps(id_),
            json.dumps({'dayOfWeekStart': get_format('FIRST_DAY_OF_WEEK')})
        )


class AdminTimeInput(WidgetWithScript, widgets.TimeInput):
    def __init__(self, attrs=None, format='%H:%M'):
        super(AdminTimeInput, self).__init__(attrs=attrs, format=format)

    def render_js_init(self, id_, name, value):
        return 'initTimeChooser({0});'.format(json.dumps(id_))


class AdminDateTimeInput(WidgetWithScript, widgets.DateTimeInput):
    def __init__(self, attrs=None, format='%Y-%m-%d %H:%M'):
        super(AdminDateTimeInput, self).__init__(attrs=attrs, format=format)

    def render_js_init(self, id_, name, value):
        return 'initDateTimeChooser({0}, {1});'.format(
            json.dumps(id_),
            json.dumps({'dayOfWeekStart': get_format('FIRST_DAY_OF_WEEK')})
        )


class AdminTagWidget(WidgetWithScript, TagWidget):
    def render_js_init(self, id_, name, value):
        return "initTagField({0}, {1});".format(
            json.dumps(id_),
            json.dumps(reverse('wagtailadmin_tag_autocomplete')))


class AdminChooser(WidgetWithScript, widgets.Input):
    input_type = 'hidden'
    choose_one_text = _("Choose an item")
    choose_another_text = _("Choose another item")
    clear_choice_text = _("Clear choice")
    link_to_chosen_text = _("Edit this item")
    show_edit_link = True

    # when looping over form fields, this one should appear in visible_fields, not hidden_fields
    # despite the underlying input being type="hidden"
    is_hidden = False

    def get_instance(self, model_class, value):
        # helper method for cleanly turning 'value' into an instance object
        if value is None:
            return None

        try:
            return model_class.objects.get(pk=value)
        except model_class.DoesNotExist:
            return None

    def get_instance_and_id(self, model_class, value):
        if value is None:
            return (None, None)
        elif isinstance(value, model_class):
            return (value, value.pk)
        else:
            try:
                return (model_class.objects.get(pk=value), value)
            except model_class.DoesNotExist:
                return (None, None)

    def value_from_datadict(self, data, files, name):
        # treat the empty string as None
        result = super(AdminChooser, self).value_from_datadict(data, files, name)
        if result == '':
            return None