from datetime import timedelta
import json
from django.conf import settings
from django.utils import timezone
from django.template import RequestContext
from django.template.loader import render_to_string
from django.views import generic
from django.contrib.admin.views.decorators import staff_member_required
from jsonview.decorators import json_view
from twitter_stream.models import FilterTerm, StreamProcess
from swapper import load_model
from django.db import models


def _render_to_string_request(request, template, dictionary):
    """
    Wrapper around render_to_string that includes the request context
    This is necessary to get all of the TEMPLATE_CONTEXT_PROCESSORS
    activated in the template.
    """
    context = RequestContext(request, dictionary)
    return render_to_string(template, context_instance=context)


def stream_status():
    terms = FilterTerm.objects.filter(enabled=True)
    processes = StreamProcess.get_current_stream_processes()
    running = False
    for p in processes:
        if p.status == StreamProcess.STREAM_STATUS_RUNNING:
            running = True
            break

    Tweet = load_model("twitter_stream", "Tweet")
    tweet_count = Tweet.count_approx()
    earliest_time = Tweet.get_earliest_created_at()
    latest_time = Tweet.get_latest_created_at()

    avg_rate = None
    if earliest_time is not None and latest_time is not None:
        avg_rate = float(tweet_count) / (latest_time - earliest_time).total_seconds()

    # Get the tweets / minute over the past 10 minutes
    tweet_counts = []
    if latest_time is not None:
        latest_time_minute = latest_time.replace(second=0, microsecond=0)

        if settings.DATABASES['default']['ENGINE'].endswith('mysql'):
            drop_seconds = "created_at - INTERVAL SECOND(created_at) SECOND"
        elif settings.DATABASES['default']['ENGINE'].endswith('postgresql_psycopg2'):
            drop_seconds = "date_trunc('minute', created_at)"
        else:
            drop_seconds = "created_at"

        tweet_counts = Tweet.objects.extra(select={
            'time': drop_seconds
        }) \
            .filter(created_at__gt=latest_time_minute - timedelta(minutes=20)) \
            .values('time') \
            .order_by('time') \
            .annotate(tweets=models.Count('id'))

        tweet_counts = list(tweet_counts)

    for row in tweet_counts:
        row['time'] = row['time'].isoformat()

    return {
        'running': running,
        'terms': [t.term for t in terms],
        'processes': processes,
        'tweet_count': tweet_count,
        'earliest': earliest_time,
        'latest': latest_time,
        'avg_rate': avg_rate,
        'timeline': tweet_counts
    }



class StatusView(generic.TemplateView):
    template_name = 'twitter_stream/status.html'

    def get_context_data(self, **kwargs):
        status = stream_status()
        status['timeline'] = json.dumps(status['timeline'])
        return {
            'status': status
        }

status = staff_member_required(StatusView.as_view())

@staff_member_required
@json_view
def json_status(request, task=None):
    """
    Returns a JSON representation of the status, with
    HTML conveniently included.
    """

    status = stream_status()

    display = _render_to_string_request(request, 'twitter_stream/status_display.html', {
        'status': status
    })

    return {
        'display': display,
        'timeline': status['timeline']
    }