"""
    Extremely simple utility class to send mails
"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import six
import os
import socket

from smtplib import SMTP, SMTP_SSL
from email.mime.application import MIMEApplication
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from getpass import getuser

from DIRAC import gLogger, S_OK, S_ERROR

__RCSID__ = "$Id$"


class Mail(object):

  def __init__(self):
    self._subject = ''
    self._message = ''
    self._mailAddress = ''
    self._html = False
    self._fromAddress = getuser() + '@' + socket.getfqdn()
    self._attachments = []
    self.esmtp_features = {}
    self._smtpPtcl = None
    self._smtpHost = None
    self._smtpPort = None
    self._smtpLogin = None
    self._smtpPasswd = None

  def _create(self, addresses):
    """ create a mail object

        :param list addresses: addresses

        :return: S_OK(object)/S_ERROR() -- contain MIMEMultipart object
    """
    if not isinstance(addresses, list):
      addresses = [addresses]

    if not self._mailAddress:
      gLogger.warn("No mail address was provided. Mail not sent.")
      return S_ERROR("No mail address was provided. Mail not sent.")

    if not self._message:
      gLogger.warn("Message body is empty")
      if not self._subject:
        gLogger.warn("Subject and body empty. Mail not sent")
        return S_ERROR("Subject and body empty. Mail not sent")

    if self._html:
      mail = MIMEText(self._message, "html")
    else:
      mail = MIMEText(self._message, "plain")

    msg = MIMEMultipart()
    msg.attach(mail)

    msg["Subject"] = self._subject
    msg["From"] = self._fromAddress
    msg["To"] = ', '.join(addresses)

    for attachment in self._attachments:
      try:
        with open(attachment, "rb") as fil:
          part = MIMEApplication(fil.read(),
                                 Name=os.path.basename(attachment)
                                 )

          part['Content-Disposition'] = 'attachment; filename="%s"' % os.path.basename(attachment)
          msg.attach(part)
      except IOError as e:
        gLogger.exception("Could not attach %s" % attachment, lException=e)

    return S_OK(msg)

  def _send(self, msg=None):
    """ send a single email message. If msg is in input, it is expected to be of email type, otherwise it will create it.

        :param object msg: MIMEMultipart object

        :return: S_OK()/S_ERROR()
    """

    if msg is None:
      addresses = self._mailAddress
      if isinstance(self._mailAddress, six.string_types):
        addresses = self._mailAddress.split(", ")

      result = self._create(addresses)
      if not result['OK']:
        return result
      msg = result['Value']

    if self._smtpPtcl == 'SSL':
      smtp = SMTP_SSL()
    else:
      smtp = SMTP()
    smtp.set_debuglevel(0)
    try:
      connParams = {}
      if self._smtpHost:
        connParams['host'] = self._smtpHost
      if self._smtpPort:
        connParams['port'] = int(self._smtpPort)
      smtp.connect(**connParams)
      smtp.ehlo_or_helo_if_needed()
      if self._smtpPtcl == 'TLS':
        smtp.starttls()
      if self._smtpLogin and self._smtpPasswd:
        smtp.login(self._smtpLogin, self._smtpPasswd)
      smtp.ehlo_or_helo_if_needed()
      smtp.sendmail(self._fromAddress, addresses, msg.as_string())
    except Exception as x:
      return S_ERROR("Sending mail failed %s" % str(x))

    smtp.quit()
    return S_OK("The mail was successfully sent")

  def __eq__(self, other):
    """ Comparing an email object to another
    """
    if isinstance(other, Mail):
      if self.__dict__ == other.__dict__:
        return True

    return False

  def __hash__(self):
    """ Comparing for sets
    """
    return hash(self._subject + self._message + self._fromAddress + self._mailAddress)
