import smtplib
from smtplib import SMTPException
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
import logging

logger = logging.getLogger(__name__)
logger.addHandler(logging.NullHandler())

"""
This module groups together related functions for
sending emails.

Module unit test: test/TestRediEmail.py
"""

def send_email_redcap_connection_error(email_settings, subject='', msg=''):
    """
    Notify the designated `REDCap support` person about problems
    with reaching REDCap

    :return True if the email was sent
    """
    sender = email_settings['redcap_support_sender_email']
    to_addr_list = email_settings['redcap_support_receiving_list']
    host = email_settings['smtp_host_for_outbound_mail']
    port = email_settings['smtp_port_for_outbound_mail']
    subject = 'Communication failure: Unable to reach REDCap instance'
    msg = 'A problem was encountered when connecting to the REDCap. Please investigate if REDCap is running.'

    logger.error('Exception: Unable to communicate with REDCap instance at: ' + email_settings['redcap_uri'])
    return send_email(host, str(port), sender, to_addr_list, None, subject, msg)

def send_email_input_data_unchanged(email_settings, subject='', msg=''):
    """
    Send a warning email to the `redcap_support_receiver_email`
    if the input file did not change for more than `batch_warning_days`

    :return True if the email was sent
    """
    sender = email_settings['redcap_support_sender_email']
    to_addr_list = email_settings['redcap_support_receiving_list']
    host = email_settings['smtp_host_for_outbound_mail']
    port = email_settings['smtp_port_for_outbound_mail']
    subject = 'Input data is static.'
    msg = """
    Administrators,
    For the past {} days the input data for the REDI application did not change.
    Please investigate.""".format(email_settings['batch_warning_days'])
    return send_email(host, str(port), sender, to_addr_list, None, subject, msg)

def send_email_data_import_completed(email_settings, body=''):
    """
    Email the html report after redi completed the data transfer
    :email_settings the dictionary produced by redi.get_email_settings()
    :body: the html string produced by transforming the xsl
        generated by redi.create_summary_report()

    :return a dictionary, with one entry for each recipient that was refused
    """
    sender = email_settings['batch_report_sender_email']
    to_addr_list = email_settings['batch_report_receiving_list']
    host = email_settings['smtp_host_for_outbound_mail']
    port = email_settings['smtp_port_for_outbound_mail']
    subject = 'Data Import Report'
    msg = MIMEMultipart()
    msg.attach(MIMEText(body, 'html'))

    refused_list = {}
    try:
        smtpObj = smtplib.SMTP(host, port)
        refused_list = smtpObj.sendmail(sender, to_addr_list, msg.as_string())
        logger.info("Successfully sent email to: " + str(to_addr_list))
    except Exception:
         logger.error("Unable to send email with subject[{}] to {}" \
                .format(subject, str(to_addr_list)))
         raise
    finally:
        smtpObj.quit()

    return refused_list

def send_email(
        host,
        port,
        sender,
        to_addr_list,
        cc_addr_list,
        subject,
        msg_body):
    """
    The email deliverer
    :to_addr_list: must be a list not a string

    :return True if the email was sent
    """
    #print ('host %s, port: %s' % (host, port))
    success = False
    try:
        smtp = smtplib.SMTP(host, port)
        header = 'From: %s\n' % sender
        header += 'To: %s\n' % ','.join(to_addr_list)
        if cc_addr_list:
            header += 'Cc: %s\n' % ','.join(cc_addr_list)
        if subject:
            header += 'Subject: %s\n\n' % subject
        msg = header + msg_body
        smtp.sendmail(sender, to_addr_list, msg)
        success = True
        logger.info(
            'Success: Email with subject [' +
            subject +
            '] was sent to:' +
            str(to_addr_list))
    except SMTPException:
        logger.error("Unable to send email with subject[{}] to {}" \
                .format(subject, str(to_addr_list)))
    return success

@@ -2687,16 +2687,109 @@
 ipart()%0A
+    msg%5B'From'%5D = sender%0A    msg%5B'To'%5D = %22,%22.join(to_addr_list)%0A    msg%5B'Subject'%5D = subject%0A
     msg.
@@ -3115,32 +3115,33 @@
 ail with subject
+ 
 %5B%7B%7D%5D to %7B%7D%22 %5C%0A  

Set the email subject properly