import datetime
import time

from django.template import loader, RequestContext
from django.core.exceptions import ObjectDoesNotExist
from django.core.xheaders import populate_xheaders
from django.db.models.fields import DateTimeField
from django.http import Http404, HttpResponse

def archive_index(request, queryset, date_field, num_latest=15,
        template_name=None, template_loader=loader,
        extra_context=None, allow_empty=True, context_processors=None,
        mimetype=None, allow_future=False, template_object_name='latest'):
    """
    Generic top-level archive of date-based objects.

    Templates: ``<app_label>/<model_name>_archive.html``
    Context:
        date_list
            List of years
        latest
            Latest N (defaults to 15) objects by date
    """
    if extra_context is None: extra_context = {}
    model = queryset.model
    if not allow_future:
        queryset = queryset.filter(**{'%s__lte' % date_field: datetime.datetime.now()})
    date_list = queryset.dates(date_field, 'year')[::-1]
    if not date_list and not allow_empty:
        raise Http404, "No %s available" % model._meta.verbose_name

    if date_list and num_latest:
        latest = queryset.order_by('-'+date_field)[:num_latest]
    else:
        latest = None

    if not template_name:
        template_name = "%s/%s_archive.html" % (model._meta.app_label, model._meta.object_name.lower())
    t = template_loader.get_template(template_name)
    c = RequestContext(request, {
        'date_list' : date_list,
        template_object_name : latest,
    }, context_processors)
    for key, value in extra_context.items():
        if callable(value):
            c[key] = value()
        else:
            c[key] = value
    return HttpResponse(t.render(c), mimetype=mimetype)

def archive_year(request, year, queryset, date_field, template_name=None,
        template_loader=loader, extra_context=None, allow_empty=False,
        context_processors=None, template_object_name='object', mimetype=None,
        make_object_list=False, allow_future=False):
    """
    Generic yearly archive view.

    Templates: ``<app_label>/<model_name>_archive_year.html``
    Context:
        date_list
            List of months in this year with objects
        year
            This year
        object_list
            List of objects published in the given month
            (Only available if make_object_list argument is True)
    """
    if extra_context is None: extra_context = {}
    model = queryset.model
    now = datetime.datetime.now()

    lookup_kwargs = {'%s__year' % date_field: year}

    # Only bother to check current date if the year isn't in the past and future objects aren't requested.
    if int(year) >= now.year and not allow_future:
        lookup_kwargs['%s__lte' % date_field] = now
    date_list = queryset.filter(**lookup_kwargs).dates(date_field, 'month')
    if not date_list and not allow_empty:
        raise Http404
    if make_object_list:
        object_list = queryset.filter(**lookup_kwargs)
    else:
        object_list = []
    if not template_name:
        template_name = "%s/%s_archive_year.html" % (model._meta.app_label, model._meta.object_name.lower())
    t = template_loader.get_template(template_name)
    c = RequestContext(request, {
        'date_list': date_list,
        'year': year,
        '%s_list' % template_object_name: object_list,
    }, context_processors)
    for key, value in extra_context.items():
        if callable(value):
            c[key] = value()
        else:
            c[key] = value
    return HttpResponse(t.render(c), mimetype=mimetype)

def archive_month(request, year, month, queryset, date_field,
        month_format='%b', template_name=None, template_loader=loader,
        extra_context=None, allow_empty=False, context_processors=None,
        template_object_name='object', mimetype=None, allow_future=False):
    """
    Generic monthly archive view.

    Templates: ``<app_label>/<model_name>_archive_month.html``
    Context:
        month:
            (date) this month
        next_month:
            (date) the first day of the next month, or None if the next month is in the future
        previous_month:
            (date) the first day of the previous month
        object_list:
            list of objects published in the given month
    """
    if extra_context is None: extra_context = {}
    try:
        date = datetime.date(*time.strptime(year+month, '%Y'+month_format)[:3])
    except ValueError:
        raise Http404

    model = queryset.model
    now = datetime.datetime.now()

    # Calculate first and last day of month, for use in a date-range lookup.
    first_day = date.replace(day=1)
    if first_day.month == 12:
        last_day = first_day.replace(year=first_day.year + 1, month=1)
    else:
        last_day = first_day.replace(month=first_day.month + 1)
    lookup_kwargs = {
        '%s__gte' % date_field: first_day,
        '%s__lt' % date_field: last_day,
    }

    # Only bother to check current date if the month isn't in the past and future objects are requested.
    if last_day >= now.date() and not allow_future:
        lookup_kwargs['%s__lte' % date_field] = now
    object_list = queryset.filter(**lookup_kwargs)
    if not object_list and not allow_empty:
        raise Http404

    # Calculate the next month, if applicable.
    if allow_future:
        next_month = last_day + datetime.timedelta(days=1)
    elif last_day < datetime.date.today():
        next_month = last_day + datetime.timedelta(days=1)
    else:
        next_month = None

    if not template_name:
        template_name = "%s/%s_archive_month.html" % (model._meta.app_label, model._meta.object_name.lower())
    t = template_loader.get_template(template_name)
    c = RequestContext(request, {
        '%s_list' % template_object_name: object_list,
        'month': date,
        'next_month': next_month,
        'previous_month': first_day - datetime.timedelta(days=1),
    }, context_processors)
    for key, value in extra_context.items():
        if callable(value):
            c[key] = value()
        else:
            c[key] = value
    return HttpResponse(t.render(c), mimetype=mimetype)

def archive_week(request, year, week, queryset, date_field,
        template_name=None, template_loader=loader,
        extra_context=None, allow_empty=True, context_processors=None,
        template_object_name='object', mimetype=None, allow_future=False):
    """
    Generic weekly archive view.

    Templates: ``<app_label>/<model_name>_archive_week.html``
    Context:
        week:
            (date) this week
        object_list:
            list of objects published in the given week
    """
    if extra_context is None: extra_context = {}
    try:
        date = datetime.date(*time.strptime(year+'-0-'+week, '%Y-%w-%U')[:3])
    except ValueError:
        raise Http404

    model = queryset.model
    now = datetime.datetime.now()

    # Calculate first and last day of week, for use in a date-range lookup.
    first_day = date
    last_day = date + datetime.timedelta(days=7)
    lookup_kwargs = {
        '%s__gte' % date_field: first_day,
        '%s__lt' % date_field: last_day,
    }

    # Only bother to check current date if the week isn't in the past and future objects aren't requested.
    if last_day >= now.date() and not allow_future:
        lookup_kwargs['%s__lte' % date_field] = now
    object_list = queryset.filter(**lookup_kwargs)
    if not object_list and not allow_empty:
        raise Http404
    if not template_name:
        template_name = "%s/%s_archive_week.html" % (model._meta.app_label, model._meta.object_name.lower())
    t = template_loader.get_template(template_name)
    c = RequestContext(request, {
        '%s_list' % template_object_name: object_list,
        'week': date,
    })
    for key, value in extra_context.items():
        if callable(value):
            c[key] = value()
        else:
            c[key] = value
    return HttpResponse(t.render(c), mimetype=mimetype)

def archive_day(request, year, month, day, queryset, date_field,
        month_format='%b', day_format='%d', template_name=None,
        template_loader=loader, extra_context=None, allow_empty=False,
        context_processors=None, template_object_name='object',
        mimetype=None, allow_future=False):
    """
    Generic daily archive view.

    Templates: ``<app_label>/<model_name>_archive_day.html``
    Context:
        object_list:
            list of objects published that day
        day:
            (datetime) the day
        previous_day
            (datetime) the previous day
        next_day
            (datetime) the next day, or None if the current day is today
    """
    if extra_context is None: extra_context = {}
    try:
        date = datetime.date(*time.strptime(year+month+day, '%Y'+month_format+day_format)[:3])
    except ValueError:
        raise Http404

    model = queryset.model
    now = datetime.datetime.now()

    if isinstance(model._meta.get_field(date_field), DateTimeField):
        lookup_kwargs = {'%s__range' % date_field: (datetime.datetime.combine(date, datetime.time.min), datetime.datetime.combine(date, datetime.time.max))}
    else:
        lookup_kwargs = {date_field: date}

    # Only bother to check current date if the date isn't in the past and future objects aren't requested.
    if date >= now.date() and not allow_future:
        lookup_kwargs['%s__lte' % date_field] = now
    object_list = queryset.filter(**lookup_kwargs)
    if not allow_empty and not object_list:
        raise Http404

    # Calculate the next day, if applicable.
    if allow_future:
        next_day = date + datetime.timedelta(days=1)
    elif date < datetime.date.today():
        next_day = date + datetime.timedelta(days=1)
    else:
        next_day = None

    if not template_name:
        template_name = "%s/%s_archive_day.html" % (model._meta.app_label, model._meta.object_name.lower())
    t = template_loader.get_template(template_name)
    c = RequestContext(request, {
        '%s_list' % template_object_name: object_list,
        'day': date,
        'previous_day': date - datetime.timedelta(days=1),
        'next_day': next_day,
    }, context_processors)
    for key, value in extra_context.items():
        if callable(value):
            c[key] = value()
        else:
            c[key] = value
    return HttpResponse(t.render(c), mimetype=mimetype)

def archive_today(request, **kwargs):
    """
    Generic daily archive view for today. Same as archive_day view.
    """
    today = datetime.date.today()
    kwargs.update({
        'year': str(today.year),
        'month': today.strftime('%b').lower(),
        'day': str(today.day),
    })
    return archive_day(request, **kwargs)

def object_detail(request, year, month, day, queryset, date_field,
        month_format='%b', day_format='%d', object_id=None, slug=None,
        slug_field='slug', template_name=None, template_name_field=None,
        template_loader=loader, extra_context=None, context_processors=None,
        template_object_name='object', mimetype=None, allow_future=False):
    """
    Generic detail view from year/month/day/slug or year/month/day/id structure.

    Templates: ``<app_label>/<model_name>_detail.html``
    Context:
        object:
            the object to be detailed
    """
    if extra_context is None: extra_context = {}
    try:
        date = datetime.date(*time.strptime(year+month+day, '%Y'+month_format+day_format)[:3])
    except ValueError:
        raise Http404

    model = queryset.model
    now = datetime.datetime.now()

    if isinstance(model._meta.get_field(date_field), DateTimeField):
        lookup_kwargs = {'%s__range' % date_field: (datetime.datetime.combine(date, datetime.time.min), datetime.datetime.combine(date, datetime.time.max))}
    else:
        lookup_kwargs = {date_field: date}

    # Only bother to check current date if the date isn't in the past and future objects aren't requested.
    if date >= now.date() and not allow_future:
        lookup_kwargs['%s__lte' % date_field] = now
    if object_id:
        lookup_kwargs['%s__exact' % model._meta.pk.name] = object_id
    elif slug and slug_field:
        lookup_kwargs['%s__exact' % slug_field] = slug
    else:
        raise AttributeError, "Generic detail view must be called with either an object_id or a slug/slugfield"
    try:
        obj = queryset.get(**lookup_kwargs)
    except ObjectDoesNotExist:
        raise Http404, "No %s found for" % model._meta.verbose_name
    if not template_name:
        template_name = "%s/%s_detail.html" % (model._meta.app_label, model._meta.object_name.lower())
    if template_name_field:
        template_name_list = [getattr(obj, template_name_field), template_name]
        t = template_loader.select_template(template_name_list)
    else:
        t = template_loader.get_template(template_name)
    c = RequestContext(request, {
        template_object_name: obj,
    }, context_processors)
    for key, value in extra_context.items():
        if callable(value):
            c[key] = value()
        else:
            c[key] = value
    response = HttpResponse(t.render(c), mimetype=mimetype)
    populate_xheaders(request, response, model, getattr(obj, obj._meta.pk.name))
    return response
