"""
MassMailer can send E-Mails via an SMTP Connection to multiple recipients.

Each E-Mail will be send individually and can be personalized. It will be send
as HTML and Plain-Text Message.
"""
import logging
import smtplib

import django.core.mail
from django.contrib.auth import get_user_model
from django.contrib.sites.models import Site
from django.template import loader

LOGGER = logging.getLogger('maillog')


class MassMailer(object):
    """
    This Class will send E-Mails via an SMTP Connection to multiple recipients.
    Each E-Mail will be send individually and can be personalized.
    It will be send as HTML and Plain-Text Message.
    """

    def __init__(self, subject=None, context=None, txt_template=None,
                 html_template=None):
        """set the subject and context for further processing."""
        self.context = context
        self.context['site'] = Site.objects.get_current()
        self.headers = {}
        self.subject = subject
        self.txt_template = loader.get_template(txt_template)
        if html_template:
            self.html_template = loader.get_template(html_template)
        else:
            self.html_template = None

    def process_mails(self, recipients):
        """ Generate personalised e-mails for each user in the recipients list.

        :param recipients: A iterateable of User objects that shoud get the mail
        :return: a iteratable of Mail Objects that should read for sending.
        """
        mail_context = self.context
        mail_queue = set()
        for recipient in recipients:
            if isinstance(recipient, get_user_model()):
                LOGGER.debug('Adding %s as Recipient' % recipient)
            else:
                LOGGER.warning('%s is not a User Object!', recipient)
                continue
            mail_context['recipient'] = recipient
            mail_to = "{first_name!s} {last_name!s} <{email!s}>".format(
                **recipient.__dict__)
            message = django.core.mail.EmailMultiAlternatives(
                subject=self.subject,
                body=self.txt_template.render(mail_context),
                to=(mail_to,),
                headers=self.headers
            )
            if self.html_template:
                message.attach_alternative(
                    self.html_template.render(mail_context), "text/html"
                )
            mail_queue.add(message)
        return mail_queue

    def set_header(self, name, value):
        """Add or modify an E-Mail Header to the Messages
        
        :param name: The Header Name that should be added
        :param value: THe Header Value that shoud be added or set
        """
        self.headers[name] = value

    def send(self, recipients=set()):
        """

        :param recipients: list of Users that should receive this Mail
        :return: 
        """
        mail_queue = self.process_mails(recipients)
        if len(mail_queue) == 0:
            LOGGER.info('No recipients for eMail "%s", bye!', self.subject)
            return True
        else:
            LOGGER.info('Sending eMail "%s" to %d people', self.subject,
                        len(mail_queue))
            LOGGER.debug(recipients)

        with django.core.mail.get_connection(fail_silently=False) as connection:
            for mail in mail_queue:
                try:
                    mail.connection = connection
                    mail.send()
                except smtplib.SMTPException:
                    LOGGER.warning("Mail failed for: %s", mail.to)
                else:
                    LOGGER.info("Mail sent successful to: %s" % mail.to)
