"""
Provides compatibility with Django 1.1

Copied from django.contrib.admin.utils
"""
from django.forms.forms import pretty_name
from django.db import models
from django.db.models.related import RelatedObject
from django.utils.encoding import force_unicode, smart_unicode, smart_str
from django.utils.translation import get_date_formats
from django.utils.text import capfirst
from django.utils import dateformat
from django.utils.html import escape
import collections


def lookup_field(name, obj, model_admin=None):
    opts = obj._meta
    try:
        f = opts.get_field(name)
    except models.FieldDoesNotExist:
        # For non-field values, the value is either a method, property or
        # returned via a callable.
        if isinstance(name, collections.Callable):
            attr = name
            value = attr(obj)
        elif (model_admin is not None and hasattr(model_admin, name) and not name == '__str__' and not name == '__unicode__'):
            attr = getattr(model_admin, name)
            value = attr(obj)
        else:
            attr = getattr(obj, name)
            if isinstance(attr, collections.Callable):
                value = attr()
            else:
                value = attr
        f = None
    else:
        attr = None
        value = getattr(obj, name)
    return f, attr, value


def label_for_field(name, model, model_admin=None, return_attr=False):
    """
    Returns a sensible label for a field name. The name can be a callable or the
    name of an object attributes, as well as a genuine fields. If return_attr is
    True, the resolved attribute (which could be a callable) is also returned.
    This will be None if (and only if) the name refers to a field.
    """
    attr = None
    try:
        field = model._meta.get_field_by_name(name)[0]
        if isinstance(field, RelatedObject):
            label = field.opts.verbose_name
        else:
            label = field.verbose_name
    except models.FieldDoesNotExist:
        if name == "__unicode__":
            label = force_unicode(model._meta.verbose_name)
            attr = str
        elif name == "__str__":
            label = smart_str(model._meta.verbose_name)
            attr = str
        else:
            if isinstance(name, collections.Callable):
                attr = name
            elif model_admin is not None and hasattr(model_admin, name):
                attr = getattr(model_admin, name)
            elif hasattr(model, name):
                attr = getattr(model, name)
            else:
                message = "Unable to lookup '%s' on %s" % (name, model._meta.object_name)
                if model_admin:
                    message += " or %s" % (model_admin.__class__.__name__,)
                raise AttributeError(message)

            if hasattr(attr, "short_description"):
                label = attr.short_description
            elif isinstance(attr, collections.Callable):
                if attr.__name__ == "<lambda>":
                    label = "--"
                else:
                    label = pretty_name(attr.__name__)
            else:
                label = pretty_name(name)
    if return_attr:
        return (label, attr)
    else:
        return label


def display_for_field(value, field):
    from django.contrib.admin.templatetags.admin_list import _boolean_icon
    from django.contrib.admin.views.main import EMPTY_CHANGELIST_VALUE

    if field.flatchoices:
        return dict(field.flatchoices).get(value, EMPTY_CHANGELIST_VALUE)
    # NullBooleanField needs special-case null-handling, so it comes
    # before the general null test.
    elif isinstance(field, models.BooleanField) or isinstance(field, models.NullBooleanField):
        return _boolean_icon(value)
    elif value is None:
        return EMPTY_CHANGELIST_VALUE
    elif isinstance(field, models.DateField) or isinstance(field, models.TimeField):
        if value:
            (date_format, datetime_format, time_format) = get_date_formats()
            if isinstance(field, models.DateTimeField):
                return capfirst(dateformat.format(value, datetime_format))
            elif isinstance(field, models.TimeField):
                return capfirst(dateformat.time_format(value, time_format))
            else:
                return capfirst(dateformat.format(value, date_format))
        else:
            return EMPTY_CHANGELIST_VALUE

    elif isinstance(field, models.DecimalField):
        if value is not None:
            return ('%%.%sf' % field.decimal_places) % value
        else:
            return EMPTY_CHANGELIST_VALUE
    elif isinstance(field, models.FloatField):
        return escape(value)
    else:
        return smart_unicode(value)
