# mailer/views.py

from django.shortcuts import render_to_response, get_object_or_404
from django.http import Http404, HttpResponseRedirect
from django.template import RequestContext
from django import newforms as forms
from django.contrib.auth.models import User, Group
from django.contrib.auth.decorators import user_passes_test
from django.template import Context, Template

from django.conf import settings

from django.core.mail import SMTPConnection, EmailMessage
# from django.core.mail import SMTPConnection
# from pycon.core.mail import EmailMessage
from pycon.core import safe_ascii_encode

from models import Message, MessageLog

class blastSettings(forms.Form):
    message = forms.ModelChoiceField(queryset=Message.objects.all())
    groups = forms.ModelMultipleChoiceField(queryset=Group.objects.all(),
                                            required=False )
    # users = forms.ModelMultipleChoiceField(queryset=User.objects.all(),
    #                                       required=False )
    # put this back to use the test4 query.
    # or for production use, but I don't see a need for it.
    # test_to = forms.CharField(required=False)
    preview = forms.BooleanField(required=False, initial=True)
    preview_count = forms.IntegerField(required=False, initial=1)


def pluck(ld,l):
    """
    reduce a list of dictionaries
    to a list of dicts that contain the keys listed in l
    """
    return [dict((k,v) for k,v in d.items() if k in l) for d in ld]


from MailBlaster import MailBlaster
class groupBlaster(MailBlaster):

    def query(self):
        g=self.query_params['bsd']['groups']
        rs=User.objects.filter(groups__in=g).distinct().values()
        return rs

# @login_required
# @user_passes_test(lambda u: u.is_staff and u.has_perm('fix.me'))
# @feature_required('SendEmailMessage', auto_create_feat=True)
@user_passes_test(lambda u: u.is_active and u.is_superuser)
def blast(request):

    """
    Give the user a <input type="text> <type="submit">
    loop back here on submit
    display either error or list of blasted.
    """

    blasted,messages,available_fields=[],[],[]

    if request.method == 'POST':
        # get the parameter(s) the user entered.
        bs = blastSettings(request.POST)
        if bs.is_valid():
            bsd = bs.cleaned_data

            mb=groupBlaster()

            # pipe to send data a query might need.
            mb.query_params={'bsd':bsd, 'request':request}

            # .query_params may not always contain these,
            # so don't try to move this into .blast_setup()
            mb.preview=bsd['preview']
            mb.message=bsd['message']

            mb.mailBlast()

            blasted=mb.details
            if blasted: # make sure there are results
                available_fields=blasted[0].keys()
                display_fields=bsd['message'].displayFields
                if display_fields:
                    blasted = pluck( blasted, display_fields.split())
                preview_count=bsd['preview_count']
                messages=mb.messages
                if preview_count:
                    messages=messages[:preview_count]
    else:
        # first time here
        bs = blastSettings()

    return render_to_response('mailer/blast.html',
        { 'operation': 'view blast',
          'title': 'Email Blaster',
          'doc': mailBlast.__doc__,
          'bs': bs,
          'available_fields': available_fields,
          'blasted': blasted,
          'messages': messages, },
             context_instance=RequestContext(request) )

def runQuery( query_name, query_params ):
    """
    Collection of querys used to drive the e-mail blaster.
    Tightly coulpled to the data in Message table by the queryName
    """
    return getattr(queries, query_name)(query_params)

def mailBlast(message, queryParams, preview=True):

    """
    Given a Message,
    run the query specified by message.toQueryName
    to get a list of addresses and other details referenced in the body
    and then send the Message.subject/body.
    This could use rewording.
    """

    # connect to the smtp server
    connection = SMTPConnection()

    # sender will fallback in the following order:
    #    queryParams['sender']
    #    message.sender
    #    settings.MAILER_EMAIL
    #    settings.DEFAULT_FROM_EMAIL (used by django mailer when sender is '')
    sender = getattr(settings, 'MAILER_FROM_EMAIL', '')
    if queryParams and 'sender' in queryParams:
        sender = queryParams['sender']
    #elif message.sender:
    #    sender = message.sender

    user = queryParams['request'].user

    # http://www.rfc.net/rfc2822.html#s3.6.5 - email headers
    headers = {
        'keywords': settings.CONFERENCE_NAME,
        'Reply-To': settings.MAILER_REPLYTO_EMAIL,
        #'X-PyCon': '2008', # what about EuroPython?
        # triggers MY spam detection
        #'X-looks-like-spam-but-its-just-carl': 'True',
        }

    subject_template=Template(message.subject)
    body_template=Template(message.body)

    # send an email for each item returned from runQuery()
    details = runQuery( message.toQueryName, queryParams )
    messages=[]
    for detail in details:
        c=Context(detail)

        subject = subject_template.render(c)
        subject = safe_ascii_encode(subject)
        body = body_template.render(c)
        to=detail['email']

        email = EmailMessage(subject, body, sender, [to] )
        if not preview:
            #print "sending to %s..."%(to),
            connection.send_messages([email])
            MessageLog(messageID=message.messageID, sender=sender,
                       user_id=user.id, to=to,
                       subject=subject, body=body).save()
        messages.append( {'subject':subject, 'body':body} )

    # connection.close()

    return details, messages

# eof mailer/views.py
