from django.db import models
from django.dispatch import receiver
from django.contrib.auth.models import User
from django.core.mail import EmailMessage
from django.conf import settings

from django.core.urlresolvers import reverse

import os.path

from signals import *

from modules.core.functions import split


class AdminMessage(models.Model):

    sender = models.EmailField(max_length=100, verbose_name='From Email Address')
    test_recipient = models.EmailField(max_length=100, verbose_name='Email Address to Test Message To', blank=True, null=True)
    subject = models.CharField(max_length=200)
    groups = models.ManyToManyField('members.MemberGroup', blank=True)
    types = models.ManyToManyField('members.MemberType', blank=True)
    email_expired = models.BooleanField(default=False, verbose_name='Send to Expired Members only (Ignores Groups and Types above)')
    message = models.TextField()
    created = models.DateTimeField(auto_now_add=True)
    add_to_locker = models.BooleanField(default=True, verbose_name="Add this message to members lockers")
    members = models.ManyToManyField('members.Member', blank=True)

    scheduled_date = models.DateField(blank=True, null=True, help_text='Email will be sent at 12:00 Noon on the date selected.')
    sent = models.BooleanField(default=False)

    def __unicode__(self):
        return self.subject

    def get_attachments(self):
        attachments = AdminMessageAttachment.objects.filter(admin_message=self, file__isnull=False)
        return attachments


class AdminMessageAttachment(models.Model):

    admin_message = models.ForeignKey('AdminMessage')
    order = models.IntegerField()
    file = models.FileField(upload_to='emails/messages', verbose_name="Attachment", blank=True, null=True)

    def __unicode__(self):
        return "%s - Attachment %s" % (self.admin_message.subject, self.order)

    def filename(self):
        return os.path.basename(self.file.name)


class Contact(models.Model):

    title = models.CharField(max_length=100)
    from_name = models.CharField(max_length=100)
    email_address = models.EmailField()

    def __unicode__(self):
        return "%s - %s" % (self.title, self.email_address)


class EmailTemplate(models.Model):

    EMAIL_TYPES = (
        (u'admin', u'Admin'),
        (u'member', u'Member'),
    )

    title = models.CharField(max_length=60)
    key = models.SlugField(unique=True)
    subject = models.CharField(max_length=100)
    content = models.TextField()
    enabled = models.BooleanField(default=True)
    from_address = models.ForeignKey('notifications.Contact', related_name="from_address")
    to_addresses = models.ManyToManyField('notifications.Contact', related_name='to_addresses', blank=True)
    email_type = models.CharField(max_length=20, choices=EMAIL_TYPES)
    editable = models.BooleanField(default=False)

    class Meta:
        ordering = ['title']

    def __unicode__(self):
        return self.title

    def get_from_address(self):
        return self.from_address.email_address

    def get_to_addresses(self):
        to_addresses = []
        for to_address in self.to_addresses.all():
            to_addresses.append(to_address.email_address)
        return to_addresses

    def send_email(self,message,to_address,bcc_addresses=False,attachments=False,reply_to=False):
        send_mail(self.key,self.subject,message,self.from_address.email_address, to_address,bcc_addresses,attachments,reply_to)


class SentEmail(models.Model):

    created = models.DateTimeField(auto_now_add=True)
    email_type = models.CharField(max_length=50)
    to_addresses = models.TextField()
    bcc_addresses = models.TextField(blank=True,null=True)
    bcc_count = models.IntegerField()
    from_address = models.CharField(max_length=200)
    subject = models.CharField(max_length=200)
    content = models.TextField()

    def __unicode__(self):
        return "%s %s" % (self.created,self.subject)

    def get_attachments(self):
        attachments = SentEmailAttachment.objects.filter(sent_email=self).order_by('order')
        return attachments

    def get_resend_addresses(self):
        import ast
        try:
            to_addresses = ast.literal_eval(self.to_addresses)
            return to_addresses
        except:
            return self.to_addresses

class SentEmailAttachment(models.Model):

    sent_email = models.ForeignKey('SentEmail')
    attachment = models.FileField(upload_to='notifications/attachments')
    order = models.IntegerField()

    def __unicode__(self):
        return "%s Attachment %s" % (self.sent_email,self.order)


# Do the sending
def add_attachments(msg, attachments):
    if attachments:
        for attachment in attachments:
            if attachment:
                if isinstance(attachment, basestring):
                    msg.attach_file(attachment)
                else:
                    msg.attach_file(attachment.path)
    return msg


def send_mail(email_key, subject, message, from_address, to_address, bcc_addresses=False, attachments=False, reply_to=False):

    bcc_string = ''
    bcc_count = 0
    if bcc_addresses:
        bcc_count = len(bcc_addresses)
        for bcc_address in bcc_addresses:
            bcc_string = "%s%s, " % (bcc_string,bcc_address)

        bcc_string = bcc_string[:-2]

    to_string = ''
    if type(to_address) is list:
        for address in to_address:
            to_string = "%s%s, " % (to_string, address)
        to_string = to_string[:-2]
    else:
        to_string = to_address

    sent_email = SentEmail(subject=subject, content=message, to_addresses=to_string, bcc_addresses=bcc_string, bcc_count=bcc_count, from_address=from_address, email_type=email_key)
    sent_email.save()

    if attachments:
        order = 1
        for attachment in attachments:
            sent_email_attachment = SentEmailAttachment(sent_email=sent_email, attachment=attachment, order=order)
            sent_email_attachment.save()
            order = order + 1

    if reply_to:
        reply_address = reply_to
    else:
        reply_address = from_address

    if settings.DEVELOPMENT:
        msg = EmailMessage(subject, message, from_address, ['daniel@calmdigital.com'])
        msg.content_subtype = "html"
        msg = add_attachments(msg, attachments)
        msg.send()
    else:
        if type(to_address) is list:
            if bcc_addresses:
                split_addresses = split(bcc_addresses, 48)
                for split_address in split_addresses:
                    msg = EmailMessage(subject, message, from_address, to_address, split_address, headers={'Reply-To': reply_address})
                    msg.content_subtype = "html"
                    msg = add_attachments(msg, attachments)
                    msg.send()
            else:
                msg = EmailMessage(subject, message, from_address, to_address, headers={'Reply-To': reply_address})
                msg.content_subtype = "html"
                msg = add_attachments(msg, attachments)
                msg.send()
        else:
            to_addresses = to_address.split(',')
            if bcc_addresses:
                split_addresses = split(bcc_addresses, 48)
                for split_address in split_addresses:
                    msg = EmailMessage(subject, message, from_address, to_addresses, split_address, headers={'Reply-To': reply_address})
                    msg.content_subtype = "html"
                    msg = add_attachments(msg, attachments)
                    msg.send()
            else:
                msg = EmailMessage(subject, message, from_address, to_addresses, headers={'Reply-To': reply_address})
                msg.content_subtype = "html"
                msg = add_attachments(msg, attachments)
                msg.send()


def resend_email_handler(sender, **kwargs):

    request = kwargs['request']
    email = kwargs['email']

    attachments = email.get_attachments()
    email_attachments = []
    for attachment in email.get_attachments():
        email_attachments.append(attachment.attachment)

    to_addresses = email.get_resend_addresses()

    if email.bcc_addresses:
        bcc_addresses = email.bcc_addresses.split(',')
    else:
        bcc_addresses = False

    send_mail(email.email_type, email.subject, email.content, email.from_address, to_addresses, bcc_addresses)


resend_email_sig.connect(resend_email_handler, dispatch_uid="resend_email_sig")
