# Although the API also has CRUD views, this module is just for 
# the regular HTML page views that pertain to CRUD, rather than the 
# JSON-formatted views that the API module handles.
#
# The CRUD aspect of this app is also the nastiest, but it works. I wrote it 
# before I knew what I was doing. It's the dullest part to rewrite though,
# so I won't get around to a significant rewrwite until later. It all works,
# after all.
 
from django.contrib.auth.decorators import login_required
from django.core.urlresolvers import reverse
from django.db import transaction
from django.forms import forms
from django.http import Http404, HttpResponseRedirect, HttpResponse
from django.shortcuts import get_object_or_404, render_to_response, redirect
from django.template import RequestContext, loader
from django.views.generic.create_update import update_object, delete_object, create_object
from django.views.generic.list_detail import object_list, object_detail
from dojango.decorators import json_response
from dojango.util import to_dojo_data, json_decode, json_encode
from flashcards.contextprocessors import subfact_form_context
from flashcards.forms import DeckForm, FactForm, FieldContentForm
from flashcards.models import FactType, Fact, Deck, CardTemplate, FieldType
from flashcards.models import FieldContent, Card
from flashcards.forms import TextbookSourceForm
from flashcards.views.shortcuts import get_deck_or_404
from books.forms import TextbookForm
import usertagging
 
 
def add_decks(request):
    '''Starting point for adding a deck, whether by creating or by downloading a shared deck.'''
    ctx = {}
    shared_decks = Deck.objects.shared_decks()
    if request.user.is_authenticated():
        shared_decks = shared_decks.exclude(owner=request.user)
        ctx['deck_list'] = Deck.objects.filter(owner=request.user, active=True).order_by('name')
    ctx['shared_deck_list'] = shared_decks
    return render_to_response('flashcards/add.html', ctx, context_instance=RequestContext(request))
 
def deck_detail(request, deck_id=None):
    deck = get_deck_or_404(request.user, deck_id)
 
    if request.user.is_authenticated():
        # Redirect if the user is already subscribed to this deck.
        subscriber = deck.get_subscriber_deck_for_user(request.user)
        if subscriber:
            return redirect(subscriber.get_absolute_url())
 
    fact_tags = deck.fact_tags()
 
    detail_args = {
        'queryset': Deck.objects.filter(active=True),
        'template_object_name': 'deck',
        'extra_context': {
            'field_types': FactType.objects.get(id=1).fieldtype_set.all().order_by('ordinal'),
            'fact_tags': fact_tags,
 
            'textbook_source_form': TextbookSourceForm(),
            'textbook_form': TextbookForm(),
        },
        'object_id': deck_id,
 
    }
    #detail_args['extra_context'].update(study_options_context(request, deck_id=deck_id))
    return object_detail(request, **detail_args)
 
 
@login_required
def facts_editor(request):
    #assume Japanese for now (model 1, the only model object)
    #get the fieldtypes for Japanese
 
    fact_type = FactType.objects.get(id=1)
    field_types = fact_type.fieldtype_set.all().order_by('ordinal')
    card_templates = fact_type.cardtemplate_set.all()
    decks = Deck.objects.filter(owner=request.user, active=True)
    context = {'field_types': field_types,
               'card_templates': card_templates,
               'decks': decks}
    return render_to_response('flashcards/facts_editor.html', context)
 
 
@login_required
def fact_update(request, fact_id):
    if request.method == 'GET':
        # if this is a subscribed fact that the subscriber hasn't copied yet, copy the fact (without its field contents) first
        fact = Fact.objects.get_for_owner_or_subscriber(fact_id, request.user)
        fact.edit_string_for_tags = usertagging.utils.edit_string_for_tags(fact.tags)
        fact_type = FactType.objects.get(id=1) #assume japanese for now
        decks = Deck.objects.filter(owner=request.user, active=True)
        card_templates = []
        activated_card_templates = [e.template for e
                                    in fact.card_set.filter(active=True)]
 
        for card_template in fact_type.cardtemplate_set.all():
            #TODO only send the id(uri)/name/status
            #card_templates.append({'card_template': card_template,
            #'activated_for_fact': (card_template in activated_card_templates)})
            card_template.activated_for_fact = (card_template
                                                in activated_card_templates)
            card_templates.append(card_template)
 
        context = {
            'fact': fact,
            'card_templates': card_templates,
            'decks': decks,
            'field_contents': fact.field_contents,
        }
 
        # subfact forms
        context.update(subfact_form_context(request))
        context['subfact_forms'] = []
        context['initial_field_content_form_count'] = fact.fieldcontent_set.count() + sum([subfact.fieldcontent_set.count() for subfact in fact.subfacts.all() if subfact.owner == request.user])
        i = 1
        field_content_offset = len(fact.field_contents)
        for subfact in fact.subfacts:
            context['subfact_forms'].append(subfact_form_context(request, subfact=subfact, field_content_offset=field_content_offset, fact_form_ordinal=i)['subfact_form'])
            i += 1
            field_content_offset += len(subfact.field_contents)
        return render_to_response('flashcards/fact_form.html', context, context_instance=RequestContext(request))
 
 
#CRUD forms
#TODO refactor into HTML/AJAX CRUD pattern
@login_required
def deck_list(request):
    decks = Deck.objects.filter(owner=request.user, active=True).order_by('name')
    context = {'container_id': 'deckDialog'}
    context['only_one_deck_exists'] = (len(decks) == 1)
 
    return object_list(request, queryset=decks, extra_context=context, template_object_name='deck')
 
 
@login_required
def deck_update(request, deck_id):
    deck = get_object_or_404(Deck, pk=deck_id)
    if deck.owner_id != request.user.id: #and not request.User.is_staff():
        raise forms.ValidationError('You do not have permission to access this flashcard deck.')
    if request.method == 'POST':
        deck_form = DeckForm(request.POST, instance=deck)
        if deck_form.is_valid():
            deck = deck_form.save()
            return HttpResponse(json_encode({'success':True}), mimetype='text/javascript')
    else:
        deck_form = DeckForm(instance=deck)
    return render_to_response('flashcards/deck_form.html', 
        {'form': deck_form,
         'deck': deck,
         'container_id': 'deckDialog',
         'post_save_redirect': '/flashcards/decks'}) #todo:post/pre redirs
 
 
@login_required
def deck_delete(request, deck_id, post_delete_redirect='/flashcards/decks'): #todo: pass post_*_redirect from urls.py
    obj = get_object_or_404(Deck, pk=deck_id)
    if obj.owner_id != request.user.id: #and not request.User.is_staff():
        raise forms.ValidationError('You do not have permission to access this flashcard deck.')
    if request.method == 'POST':
        if obj.subscriber_decks.filter(active=True).count() > 0: #exists():
            obj.active = False
            obj.save()
        else:
            obj.delete_cascading()
        return HttpResponse(json_encode({'success':True}), mimetype='text/javascript')
    else:
        return render_to_response('flashcards/deck_confirm_delete.html',
            {'deck': obj,
             'post_delete_redirect': post_delete_redirect,
             'container_id': 'deckDialog'})
 
@login_required
def deck_create(request,
                post_save_redirect=None,
                cancel_redirect='add_decks'):
    cancel_redirect = reverse(cancel_redirect)
 
    if post_save_redirect is not None:
        post_save_redirect = reverse(post_save_redirect)
 
    if request.method == 'POST':
 
        deck_form = DeckForm(request.POST)
        if deck_form.is_valid():
            new_deck = deck_form.save(commit=False)
            new_deck.owner = request.user
            new_deck.save()
 
            if 'tags' in deck_form.cleaned_data:
                    new_deck.tags = deck_form.cleaned_data['tags']
 
            if post_save_redirect is None:
                post_save_redirect = new_deck.get_absolute_url()
            else:
                post_save_redirect = reverse(post_save_redirect)
 
            return HttpResponse(json_encode({'success': True, 'postRedirect': post_save_redirect}), mimetype='text/javascript')
        else:
            #FIXME post_redirect for failure? handle in ajax?
            return HttpResponse(json_encode({'success': False}), mimetype='text/javascript')
    else:
            deck_form = DeckForm()
    return render_to_response('flashcards/deck_form.html', 
        {'form': deck_form,
         'post_save_redirect': post_save_redirect,
         'cancel_redirect': cancel_redirect,
        } , context_instance=RequestContext(request)) #todo:post/pre redirs
 
 
 
 
 
@login_required
def deck_export_to_csv(request, deck_id):
    '''
    Terrible CSV generator.
 
    sample:
        Expression,Reading,Meaning,Production,Recognition
        TAberu,TA[ta]beru,to eat,off,on
    '''
    deck = get_object_or_404(Deck, pk=deck_id)
 
    if deck.owner_id != request.user.id: #and not request.User.is_staff():
        raise forms.ValidationError('You do not have permission to access this flashcard deck.')
 
    return deck.export_to_csv()