#Django core bits
from django.shortcuts import render_to_response, get_object_or_404
from django.template import RequestContext, loader, Context
from django.contrib.auth.decorators import login_required, permission_required
from django.db.models import Q
from django.contrib.sites.models import Site
from django.conf import settings
from django.http import HttpResponseRedirect, Http404, HttpResponse
from django.core.urlresolvers import reverse
from django.contrib.auth.models import User, Group
from django.contrib import messages
from django.template.defaultfilters import slugify
from datetime import datetime, date, time
import csv

from modules.core.decorators import superuser_only
from modules.core.functions import *

#Forms
from forms import *

#Models
from models import *
from modules.members.models import *

@permission_required('admin_users.can_access_elections')
def elections(request):

    enabled_elections = Election.objects.filter(enabled=True).order_by('name')
    disabled_elections = Election.objects.filter(enabled=False).order_by('name')

    return render_to_response('admin/elections/elections.html',{'enabled_elections':enabled_elections,'disabled_elections':disabled_elections},context_instance=RequestContext(request))

@permission_required('admin_users.can_access_elections')
def add_election(request):

    election_form = ElectionForm()

    if request.POST:
        election_form = ElectionForm(request.POST)

        try:
            election = election_form.save(commit=False)
            election.slug = slugify_unique(election.name,Election,'slug')
            election.save()

            messages.success(request,'Election has been created')
            return HttpResponseRedirect(reverse('admin_elections'))

        except:
            messages.error(request,'Could not create election')

    return render_to_response('admin/elections/add-election.html',{'election_form':election_form},context_instance=RequestContext(request))


@permission_required('admin_users.can_access_elections')
def edit_election(request,election_id):

    election = get_object_or_404(Election,id=election_id)

    election_form = ElectionForm(instance=election)

    if request.POST:

        election_form = ElectionForm(request.POST,instance=election)

        if election_form.is_valid():
            try:
                election_form.save()

                messages.success(request,'Election Saved')
                return HttpResponseRedirect(reverse('admin_elections'))

            except:
                messages.error(request,'Could not update election')

    return render_to_response('admin/elections/edit-election.html',{'election':election,'election_form':election_form},context_instance=RequestContext(request))

@permission_required('admin_users.can_access_elections')
def duplicate_election(request,election_id):

    initial_election = get_object_or_404(Election,id=election_id)
    election_form = ElectionForm(instance=initial_election)

    if request.POST:

        election_form = ElectionForm(request.POST)

        if election_form.is_valid():

            try:
                election = election_form.save(commit=False)
                election.slug = slugify_unique(election.name,Election,'slug')
                election.save()

                for initial_position in initial_election.get_positions():
                    new_position = ElectionPosition(name=initial_position.name,order=initial_position.order,election=election)
                    new_position.save()

                messages.success(request,'Election Duplicated')

                return HttpResponseRedirect(reverse('admin_elections'))

            except:
                messages.error(request,'Could not duplicate election')

    return render_to_response('admin/elections/duplicate-election.html',{'election':initial_election,'election_form':election_form},context_instance=RequestContext(request))

@permission_required('admin_users.can_access_elections')
def delete_election(request,election_id):

    election = get_object_or_404(Election,id=election_id)

    try:
        election.delete()

        messages.success(request,'Election Deleted')

    except:
        messages.error(request,'Could not delete election')

    return HttpResponseRedirect(reverse('admin_elections'))

@permission_required('admin_users.can_access_elections')
def enable_election(request,election_id):

    election = get_object_or_404(Election,id=election_id)

    try:
        election.enabled = True
        election.save()

        messages.success(request,'Election Enabled')
    except:
        messages.error(request,'Could not enable election')

    return HttpResponseRedirect(reverse('admin_elections'))

@permission_required('admin_users.can_access_elections')
def disable_election(request,election_id):

    election = get_object_or_404(Election,id=election_id)

    try:
        election.enabled = False
        election.save()

        messages.success(request,'Election Disabled')
    except:
        messages.error(request,'Could not disable election')

    return HttpResponseRedirect(reverse('admin_elections'))


@permission_required('admin_users.can_access_elections')
def election_positions(request,election_id):

    election = get_object_or_404(Election,id=election_id)

    election_positions = ElectionPosition.objects.filter(election=election)

    return render_to_response('admin/elections/election-positions.html',{'election':election,'election_positions':election_positions},context_instance=RequestContext(request))

@permission_required('admin_users.can_access_elections')
def add_election_position(request,election_id):

    election = get_object_or_404(Election,id=election_id)

    election_position_form = ElectionPositionForm()

    if request.POST:
        election_position_form = ElectionPositionForm(request.POST)

        if election_position_form.is_valid():

            try:
                election_position = election_position_form.save(commit=False)
                election_position.election = election
                election_position.save()

                messages.success(request,'Election Position Created')

                return HttpResponseRedirect(reverse('admin_elections_election_positions',args=[election.id]))

            except:
                messages.error(request,'Could not create election position')

    return render_to_response('admin/elections/add-election-position.html',{'election':election,'election_position_form':election_position_form},context_instance=RequestContext(request))

@permission_required('admin_users.can_access_elections')
def edit_election_position(request,election_id,position_id):

    election = get_object_or_404(Election,id=election_id)
    election_position = get_object_or_404(ElectionPosition,id=position_id,election=election)

    election_position_form = ElectionPositionForm(instance=election_position)

    if request.POST:
        election_position_form = ElectionPositionForm(request.POST,instance=election_position)

        if election_position_form.is_valid():

            try:
                election_position_form.save()
                messages.success(request,'Election Position Updated')

                return HttpResponseRedirect(reverse('admin_elections_election_positions',args=[election.id]))
            except:
                messages.error(request,'Could not update election position')

    return render_to_response('admin/elections/edit-election-position.html',{'election':election,'election_position':election_position,'election_position_form':election_position_form},context_instance=RequestContext(request))

@permission_required('admin_users.can_access_elections')
def delete_election_position(request,election_id,position_id):

    election = get_object_or_404(Election,id=election_id)
    election_position = get_object_or_404(ElectionPosition,id=position_id,election=election)

    try:
        election_position.delete()
        messages.success(request,'Election Position Deleted')
    except:
        messages.error(request,'Could not delete Election Position')

    return HttpResponseRedirect(reverse('admin_elections_election_positions',args=[election.id]))


@permission_required('admin_users.can_access_elections')
def election_candidates(request,election_id):

    election = get_object_or_404(Election,id=election_id)

    election_positions = ElectionPosition.objects.filter(election=election).order_by('order')

    pending_candidates = ElectionCandidate.objects.filter(election=election,status='pending').order_by('-created')
    rejected_candidates = ElectionCandidate.objects.filter(election=election,status='rejected').order_by('-created')

    return render_to_response('admin/elections/election-candidates.html',{'election':election,'election_positions':election_positions,'pending_candidates':pending_candidates,'rejected_candidates':rejected_candidates},context_instance=RequestContext(request))

@permission_required('admin_users.can_access_elections')
def add_election_candidate(request,election_id):

    election = get_object_or_404(Election,id=election_id)
    election_positions = ElectionPosition.objects.filter(election=election).order_by('order')

    election_candidate_form = AddElectionCandidateForm()
    election_candidate_form.fields['position'].queryset = election_positions

    if request.POST:
        election_candidate_form = AddElectionCandidateForm(request.POST)

        if election_candidate_form.is_valid():
            #try:
            election_candidate = election_candidate_form.save(commit=False)
            election_candidate.election = election

            election_candidate.title = election_candidate.member.title
            election_candidate.given_name = election_candidate.member.given_name
            election_candidate.surname = election_candidate.member.surname
            election_candidate.email = election_candidate.member.user.email
            election_candidate.telephone = election_candidate.member.telephone
            election_candidate.status = 'approved'
            election_candidate.save()

            messages.success(request,'Election Candidate Added')

            return HttpResponseRedirect(reverse('admin_elections_election_candidates',args=[election.id]))

            #except:
            #    messages.error(request,'Could not add Candidate')

    return render_to_response('admin/elections/add-candidate.html',{'election':election,'election_candidate_form':election_candidate_form},context_instance=RequestContext(request))

@permission_required('admin_users.can_access_elections')
def view_election_candidate(request,election_id,candidate_id):

    election = get_object_or_404(Election,id=election_id)
    election_candidate = get_object_or_404(ElectionCandidate,id=candidate_id,election=election)

    return render_to_response('admin/elections/view-candidate.html',{'election':election,'election_candidate':election_candidate},context_instance=RequestContext(request))


@permission_required('admin_users.can_access_elections')
def edit_election_candidate(request,election_id,candidate_id):

    election = get_object_or_404(Election,id=election_id)
    election_candidate = get_object_or_404(ElectionCandidate,id=candidate_id,election=election)

    election_candidate_form = UpdateElectionCandidateForm(instance=election_candidate)

    election_positions = ElectionPosition.objects.filter(election=election).order_by('order')
    election_candidate_form.fields['position'].queryset = election_positions

    if request.POST:
        election_candidate_form = UpdateElectionCandidateForm(request.POST,request.FILES,instance=election_candidate)
        if election_candidate_form.is_valid():
            try:
                election_candidate = election_candidate_form.save()

                messages.success(request,'Election Candidate Saved')

                return HttpResponseRedirect(reverse('admin_elections_election_candidates',args=[election.id]))

            except:
                messages.error(request,'Could not update Candidate')


    return render_to_response('admin/elections/edit-candidate.html',{'election':election,'election_candidate':election_candidate,'election_candidate_form':election_candidate_form},context_instance=RequestContext(request))

@permission_required('admin_users.can_access_elections')
def approve_election_candidate(request,election_id,candidate_id):

    election = get_object_or_404(Election,id=election_id)
    candidate = get_object_or_404(ElectionCandidate,id=candidate_id,election=election)

    try:
        candidate.status = 'approved'
        candidate.save()
        messages.success(request,'Candidate Approved')
    except:
        messages.error(request,'Could not Approve Candidate')

    return HttpResponseRedirect(reverse('admin_elections_election_candidates',args=[election.id]))

@permission_required('admin_users.can_access_elections')
def reject_election_candidate(request,election_id,candidate_id):

    election = get_object_or_404(Election,id=election_id)
    candidate = get_object_or_404(ElectionCandidate,id=candidate_id,election=election)

    try:
        candidate.status = 'rejected'
        candidate.save()
        messages.success(request,'Candidate Rejected')
    except:
        messages.error(request,'Could not Reject Candidate')

    return HttpResponseRedirect(reverse('admin_elections_election_candidates',args=[election.id]))


@permission_required('admin_users.can_access_elections')
def delete_election_candidate(request,election_id,candidate_id):

    election = get_object_or_404(Election,id=election_id)
    candidate = get_object_or_404(ElectionCandidate,id=candidate_id,election=election)

    try:
        candidate.delete()
        messages.success(request,'Candidate Deleted')
    except:
        messages.error(request,'Could not Delete Candidate')

    return HttpResponseRedirect(reverse('admin_elections_election_candidates',args=[election.id]))

@permission_required('admin_users.can_access_elections')
def download_candidates(request,election_id):

    election = get_object_or_404(Election,id=election_id)
    election_candidates = ElectionCandidate.objects.filter(election=election,status='approved').order_by('position__order','created')

    fields = ['Title','Given Name','Surname','Email Address','Telephone','Position Applied For','Qualifications','CCST Status','Current Post','Hospital / Clinic','Manifesto','Sponsor 1','Sponsor 1 Confirmed','Sponsor 2','Sponsor 2 Confirmed']

    response = HttpResponse(content_type='text/csv')
    response['Content-Disposition'] = "attachment; filename=election_candidates.csv"

    writer = csv.writer(response)
    writer.writerow(fields)

    for candidate in election_candidates:

        if candidate.sponsor_confirmed_1:
            confirmed_1 = 'Yes'
        else:
            confirmed_1 = 'No'

        if candidate.sponsor_confirmed_2:
            confirmed_2 = 'Yes'
        else:
            confirmed_2 = 'No'


        submission_array = [candidate.title,candidate.given_name,candidate.surname,candidate.email,candidate.telephone,candidate.position,candidate.qualifications,candidate.ccst_status,candidate.current_post,candidate.hospital,candidate.manifesto,candidate.sponsor_email_1,confirmed_1,candidate.sponsor_email_2,confirmed_2]
        writer.writerow([unicode(s).encode("utf-8") for s in submission_array])

    return response


@permission_required('admin_users.can_access_elections')
def election_votes(request,election_id):

    election = get_object_or_404(Election,id=election_id)
    election_positions = ElectionPosition.objects.filter(election=election).order_by('order')

    return render_to_response('admin/elections/election-votes.html',{'election':election,'election_positions':election_positions},context_instance=RequestContext(request))


@permission_required('admin_users.can_access_elections')
def download_votes(request,election_id):

    election = get_object_or_404(Election,id=election_id)
    election_candidates = ElectionCandidate.objects.filter(election=election,status='approved').order_by('position__order','created')

    fields = ['Given Name','Surname','Email Address','Position','Votes']

    response = HttpResponse(content_type='text/csv')
    response['Content-Disposition'] = "attachment; filename=election_votes.csv"

    writer = csv.writer(response)
    writer.writerow(fields)

    for candidate in election_candidates:

        submission_array = [candidate.given_name,candidate.surname,candidate.member.user.email,candidate.position,candidate.get_vote_count()]
        writer.writerow([unicode(s).encode("utf-8") for s in submission_array])

    return response
