from apps.utils import querycleaner
from apps.utils.querycleaner import clean_query
from datetime import datetime, timedelta
from django.contrib.auth.decorators import login_required
from django.contrib.humanize.templatetags.humanize import naturalday
from django.core.exceptions import PermissionDenied
from django.http import HttpResponse
from django.shortcuts import get_object_or_404, render_to_response
from django.template import RequestContext, loader
from django.template.loader import render_to_string
from django.views.decorators.http import require_GET
from dojango.decorators import json_response
from dojango.util import to_dojo_data, json_decode, json_encode
from flashcards.models import CardHistory, Card
from flashcards.models.constants import GRADE_NONE, GRADE_HARD, GRADE_GOOD, GRADE_EASY
from flashcards.views.decorators import ApiException
from flashcards.views.decorators import flashcard_api as api
from flashcards.views.decorators import has_card_query_filters
 
 
@login_required
def index(request):
    context = {
    }
    return render_to_response('stats/index.html', context,
        context_instance=RequestContext(request))
 
 
 
 
 
# Views for graphs
 
 
MATURITY_COLORS = {
    'new':      '#62C691',
    'young':    '#7074C5',#'#49388a',
    'mature':   '#E4C670',
}
 
MATURITY_NAMES = {
    'new': 'New',
    'young': 'Started',
    'mature': 'Proficient',
}
 
 
@api
@require_GET
def repetitions(request):
    '''
    Graph data for repetitions per day.
    '''
    series = []
    user = request.user
    user_items = CardHistory.objects.of_user(user)
 
    for maturity in ['new', 'young', 'mature']:
        data = getattr(user_items, maturity)().repetitions()
 
        # Convert the values into pairs (from hashes)
        data = list((value['reviewed_on'], value['repetitions'])
                      for value in data)
 
        series.append({
            'name': MATURITY_NAMES.get(maturity, maturity),
            'data': data,
            'color': MATURITY_COLORS[maturity],
        })
 
    return {'series': series}
 
@api
@require_GET
def due_counts(request):
    '''Due per day in future.'''
    series = []
    user = request.user
    user_items = Card.objects.common_filters(user)
 
    for maturity in ['young', 'mature']:
        items = getattr(user_items, maturity)(user)
 
        today_count = items.due_today_count()
 
        data = [(datetime.today(), today_count,)]
 
        future_counts = getattr(user_items, maturity)(user).future_due_counts()
 
        # Convert the values into pairs (from hashes)
        data.extend(list((value['due_on'], value['due_count'])
                      for value in future_counts))
 
        series.append({
            'name': MATURITY_NAMES.get(maturity, maturity),
            'data': data,
            'color': MATURITY_COLORS[maturity],
        })
 
    return {'series': series}
 
 
 
@api
@require_GET
@has_card_query_filters
def daily_repetition_history(request, deck=None, tags=None):
    '''
    For now, just gives review counts per day. Doesn't split into correct/incorrect.
    The last element is today. Each element before that is one day earlier.
    '''
    # How many days of history?
    days = int(request.GET.get('days', 60))
    from_ = datetime.utcnow() - timedelta(days=days)
 
    user_items = CardHistory.objects.of_user(request.user).filter(
        reviewed_at__gte=from_)
 
    if deck:
        user_items = user_items.of_deck(deck)
 
    data = [val['repetitions'] for val in user_items.repetitions()]
    return data
 
    #return [199, 115, 64, 92, 40, 60, 56, 85, 2, 4, 8, 64, 41, 1, 44, 19, 115, 64, 82, 40, 60, 56, 5, 288, 4, 8, 64, 41, 1, 44]
    #return {
    #    'series': [
    #        {
    #            'color': 'green',
    #            'data': [29.9, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5, 216.4, 194.1, 95.6, 54.4]
    #        },
    #        {
    #            'color': 'red',
    #            'data': [19.9, 11.5, 6.4, 9.2, 4.0, 6.0, 5.6, 8.5, 6.4, 4.1, 1, 4.4]
    #        }
    #    ]
     #}
 
 
 
 
 
 
 
########################################
#
# Used for end of review session stats
#
########################################
 
#TODO needed? so far, unused.
#@api
#@require_GET
#@has_card_query_filters
#def scheduling_summary(request, deck=None, tags=None):
#    '''
#    Provides the following data:
#        # due now
#        # due tomorrow
#        # new cards
#        next card's due date (datetime)
#    '''
#    cards = Card.objects.common_filters(
#        request.user, deck=deck, tags=tags)
 
#    data = {
#        'due_now': cards.due(request.user).count(),
#        'due_tomorrow': Card.objects.count_of_cards_due_tomorrow(
#                request.user, deck=deck, tags=tags),
#        'new': cards.new().count(),
#        'next_card_due_at': cards.next_card_due_at(),
#    }
#    return data
 
 
 
########################################
#
# Individual card and deck stats
#
########################################
 
 
#@api
#@require_GET
#def card_stats_json(request, card_id):
#    '''
#    '''
#    card = get_object_or_404(Card, pk=card_id)
 
#    if card.owner != request.user:
#        raise PermissionDenied('You do not own this flashcard.')
 
#    #first_reviewed_at = card.cardhistory_set.
 
#    stats = {
#        'createdAt':        card.fact.created_at,
#        'modifiedAt':       card.fact.modified_at,
#        'firstReviewedAt':  card.first_reviewed_at,
#        'dueAt':            card.due_at,
#        'interval':         card.interval,
#        'easeFactor':       card.ease_factor,
#        'lastDueAt':        card.last_due_at,
#        'lastInterval':     card.last_interval,
#        'lastEaseFactor':   card.last_ease_factor,
#        'lastFailedAt':     card.last_failed_at,
#        'lastReviewGrade':  card.last_review_grade,
#        'reviewCount':      card.review_count,
 
#        'averageDuration':         card.average_duration(),
#        'averageQuestionDuration': card.average_question_duration(),
#        'totalDuration':           card.total_duration(),
#        'totalQuestionDuration':   card.total_question_duration(),
 
#        'template':         card.template,
#    }
 
#    return stats
 
 
@login_required
def card_stats(request, card_id):
    '''
    Similar to `card_stats_json` but actually renders it in HTML.
    '''
    card = get_object_or_404(Card, pk=card_id)
 
    if not card.deck.shared and card.owner != request.user:
        raise PermissionDenied('You do not own this flashcard.')
 
    context = {
        'card': card,
        'early_review': card.due_at and card.due_at > datetime.utcnow(),
    }
 
    return render_to_response('stats/card_stats.html', context,
        context_instance=RequestContext(request))