"""
Celery queued tasks for Helios

2010-08-01
ben@adida.net
"""
import copy
from celery import shared_task
from celery.utils.log import get_logger

import signals
from models import CastVote, Election, Voter, VoterFile
from view_utils import render_template_raw


@shared_task
def cast_vote_verify_and_store(cast_vote_id, status_update_message=None, **kwargs):
    cast_vote = CastVote.objects.get(id=cast_vote_id)
    result = cast_vote.verify_and_store()

    voter = cast_vote.voter
    election = voter.election
    user = voter.get_user()

    if result:
        # send the signal
        signals.vote_cast.send(sender=election, election=election, user=user, voter=voter, cast_vote=cast_vote)

        if status_update_message and user.can_update_status():
            user.update_status(status_update_message)
    else:
        logger = get_logger(cast_vote_verify_and_store.__name__)
        logger.error("Failed to verify and store %d" % cast_vote_id)


@shared_task
def voters_email(election_id, subject_template, body_template, extra_vars={},
                 voter_constraints_include=None, voter_constraints_exclude=None):
    """
    voter_constraints_include are conditions on including voters
    voter_constraints_exclude are conditions on excluding voters
    """
    election = Election.objects.get(id=election_id)

    # select the right list of voters
    voters = election.voter_set.all()
    if voter_constraints_include:
        voters = voters.filter(**voter_constraints_include)
    if voter_constraints_exclude:
        voters = voters.exclude(**voter_constraints_exclude)

    for voter in voters:
        single_voter_email.delay(voter.uuid, subject_template, body_template, extra_vars)


@shared_task
def voters_notify(election_id, notification_template, extra_vars={}):
    election = Election.objects.get(id=election_id)
    for voter in election.voter_set.all():
        single_voter_notify.delay(voter.uuid, notification_template, extra_vars)


@shared_task
def single_voter_email(voter_uuid, subject_template, body_template, extra_vars={}):
    voter = Voter.objects.get(uuid=voter_uuid)

    the_vars = copy.copy(extra_vars)
    the_vars.update({'voter': voter})

    subject = render_template_raw(None, subject_template, the_vars)
    body = render_template_raw(None, body_template, the_vars)

    voter.send_message(subject, body)


@shared_task
def single_voter_notify(voter_uuid, notification_template, extra_vars={}):
    voter = Voter.objects.get(uuid=voter_uuid)

    the_vars = copy.copy(extra_vars)
    the_vars.update({'voter': voter})

    notification = render_template_raw(None, notification_template, the_vars)

    voter.send_notification(notification)


@shared_task
def election_compute_tally(election_id):
    election = Election.objects.get(id=election_id)
    election.compute_tally()

    election_notify_admin.delay(election_id=election_id,
                                subject="encrypted tally computed",
                                body="""
The encrypted tally for election %s has been computed.

--
Helios
""" % election.name)

    if election.has_helios_trustee():
        tally_helios_decrypt.delay(election_id=election.id)


@shared_task
def tally_helios_decrypt(election_id):
    election = Election.objects.get(id=election_id)
    election.helios_trustee_decrypt()
    election_notify_admin.delay(election_id=election_id,
                                subject='Helios Decrypt',
                                body="""
Helios has decrypted its portion of the tally
for election %s.

--
Helios
""" % election.name)


@shared_task
def voter_file_process(voter_file_id):
    voter_file = VoterFile.objects.get(id=voter_file_id)
    voter_file.process()
    election_notify_admin.delay(election_id=voter_file.election.id,
                                subject='voter file processed',
                                body="""
Your voter file upload for election %s
has been processed.

%s voters have been created.

--
Helios
""" % (voter_file.election.name, voter_file.num_voters))


@shared_task
def election_notify_admin(election_id, subject, body):
    election = Election.objects.get(id=election_id)
    election.admin.send_message(subject, body)

[((378, 415), 'models.CastVote.objects.get', 'CastVote.objects.get', ([], {'id': 'cast_vote_id'}), '(id=cast_vote_id)\n', (398, 415), False, 'from models import CastVote, Election, Voter, VoterFile\n'), ((1297, 1333), 'models.Election.objects.get', 'Election.objects.get', ([], {'id': 'election_id'}), '(id=election_id)\n', (1317, 1333), False, 'from models import CastVote, Election, Voter, VoterFile\n'), ((1816, 1852), 'models.Election.objects.get', 'Election.objects.get', ([], {'id': 'election_id'}), '(id=election_id)\n', (1836, 1852), False, 'from models import CastVote, Election, Voter, VoterFile\n'), ((2088, 2122), 'models.Voter.objects.get', 'Voter.objects.get', ([], {'uuid': 'voter_uuid'}), '(uuid=voter_uuid)\n', (2105, 2122), False, 'from models import CastVote, Election, Voter, VoterFile\n'), ((2139, 2160), 'copy.copy', 'copy.copy', (['extra_vars'], {}), '(extra_vars)\n', (2148, 2160), False, 'import copy\n'), ((2214, 2267), 'view_utils.render_template_raw', 'render_template_raw', (['None', 'subject_template', 'the_vars'], {}), '(None, subject_template, the_vars)\n', (2233, 2267), False, 'from view_utils import render_template_raw\n'), ((2279, 2329), 'view_utils.render_template_raw', 'render_template_raw', (['None', 'body_template', 'the_vars'], {}), '(None, body_template, the_vars)\n', (2298, 2329), False, 'from view_utils import render_template_raw\n'), ((2471, 2505), 'models.Voter.objects.get', 'Voter.objects.get', ([], {'uuid': 'voter_uuid'}), '(uuid=voter_uuid)\n', (2488, 2505), False, 'from models import CastVote, Election, Voter, VoterFile\n'), ((2522, 2543), 'copy.copy', 'copy.copy', (['extra_vars'], {}), '(extra_vars)\n', (2531, 2543), False, 'import copy\n'), ((2602, 2660), 'view_utils.render_template_raw', 'render_template_raw', (['None', 'notification_template', 'the_vars'], {}), '(None, notification_template, the_vars)\n', (2621, 2660), False, 'from view_utils import render_template_raw\n'), ((2775, 2811), 'models.Election.objects.get', 'Election.objects.get', ([], {'id': 'election_id'}), '(id=election_id)\n', (2795, 2811), False, 'from models import CastVote, Election, Voter, VoterFile\n'), ((3263, 3299), 'models.Election.objects.get', 'Election.objects.get', ([], {'id': 'election_id'}), '(id=election_id)\n', (3283, 3299), False, 'from models import CastVote, Election, Voter, VoterFile\n'), ((3660, 3699), 'models.VoterFile.objects.get', 'VoterFile.objects.get', ([], {'id': 'voter_file_id'}), '(id=voter_file_id)\n', (3681, 3699), False, 'from models import CastVote, Election, Voter, VoterFile\n'), ((4140, 4176), 'models.Election.objects.get', 'Election.objects.get', ([], {'id': 'election_id'}), '(id=election_id)\n', (4160, 4176), False, 'from models import CastVote, Election, Voter, VoterFile\n'), ((595, 703), 'signals.vote_cast.send', 'signals.vote_cast.send', ([], {'sender': 'election', 'election': 'election', 'user': 'user', 'voter': 'voter', 'cast_vote': 'cast_vote'}), '(sender=election, election=election, user=user, voter\n    =voter, cast_vote=cast_vote)\n', (617, 703), False, 'import signals\n'), ((844, 891), 'celery.utils.log.get_logger', 'get_logger', (['cast_vote_verify_and_store.__name__'], {}), '(cast_vote_verify_and_store.__name__)\n', (854, 891), False, 'from celery.utils.log import get_logger\n')]