# -*- coding: utf-8 -*-

# Copyright (c) 2003 - 2005 Detlev Offenbach <detlev@die-offenbachs.de>
#

"""
Module implementing a dialog to send bug reports.
"""

import sys
import os
import mimetypes
import smtplib
import socket

from qt import *
from qtext import QSCINTILLA_VERSION_STR

from KdeQt import KQFileDialog, KQMessageBox, KQInputDialog
import KdeQt

from EmailForm import EmailForm
from Info import Program, Version, BugAddress
import Preferences
import Utilities

from email import Encoders
from email.MIMEBase import MIMEBase
from email.MIMEText import MIMEText
from email.MIMEImage import MIMEImage
from email.MIMEAudio import MIMEAudio
from email.MIMEMultipart import MIMEMultipart

from Refactoring.Refactoring import Refactoring, BRM_VERSION_STR

class EmailDialog(EmailForm):
    """
    Class implementing a dialog to send bug reports.
    """
    def __init__(self, parent=None):
        """
        Constructor
        
        @param parent parent widget of this dialog (QWidget)
        """
        EmailForm.__init__(self, parent)
        height = self.height()
        self.mainSplitter.setSizes([int(0.7 * height), int(0.3 * height)])
        sig = Preferences.getUser("Signature")
        if sig:
            self.message.setText(sig)
            self.message.setCursorPosition(0, 0)
        
    def handleSend(self):
        """
        Private slot to send the email message.
        """
        if self.attachments.childCount():
            msg = self.createMultipartMail()
        else:
            msg = self.createSimpleMail()
            
        qApp.setOverrideCursor(Qt.waitCursor)
        qApp.processEvents()
        ok = self.sendmail(msg)
        qApp.restoreOverrideCursor()
        
        if ok:
            self.accept()
        
    def createSimpleMail(self):
        """
        Private method to create a simple mail message.
        
        @return string containing the mail message
        """
        try:
            import sipconfig
            sip_version_str = sipconfig.Configuration().sip_version_str
        except ImportError:
            sip_version_str = "sip version not available"
        
        if KdeQt.isKDE():
            msgtext = ("%s\r\n----\r\nVersion Numbers:\r\n  Python %s\r\n" + \
                "  KDE %s\r\n  PyKDE %s\r\n  Qt %s\r\n" + \
                "  PyQt %s\r\n  sip %s\r\n  QScintilla %s\r\n  %s %s\r\n" + \
                "  Bicycle Repair Man %s\r\n\r\nPlatform: %s\r\n%s\r\n") % \
                (unicode(self.message.text()), sys.version.split()[0],
                str(KdeQt.kdeVersionString()), str(KdeQt.pyKdeVersionString()),
                str(QT_VERSION_STR), str(PYQT_VERSION_STR), str(sip_version_str),
                str(QSCINTILLA_VERSION_STR),
                Program, Version, BRM_VERSION_STR, sys.platform, sys.version)
        else:
            msgtext = ("%s\r\n----\r\nVersion Numbers:\r\n  Python %s\r\n  Qt %s\r\n" + \
                "  PyQt %s\r\n  sip %s\r\n  QScintilla %s\r\n  %s %s\r\n" + \
                "  Bicycle Repair Man %s\r\n\r\nPlatform: %s\r\n%s\r\n") % \
                (unicode(self.message.text()), sys.version.split()[0],
                str(QT_VERSION_STR), str(PYQT_VERSION_STR), str(sip_version_str),
                str(QSCINTILLA_VERSION_STR),
                Program, Version, BRM_VERSION_STR, sys.platform, sys.version)
        
        msg = MIMEText(msgtext, _charset = sys.getdefaultencoding())
        msg['From']    = unicode(Preferences.getUser("Email"))
        msg['To']      = BugAddress
        msg['Subject'] = '[eric3] %s' % unicode(self.subject.text())
            
        return msg.as_string()
        
    def createMultipartMail(self):
        """
        Private method to create a multipart mail message.
        
        @return string containing the mail message
        """
        try:
            import sipconfig
            sip_version_str = sipconfig.Configuration().sip_version_str
        except ImportError:
            sip_version_str = "sip version not available"
        
        mpPreamble = ("This is a MIME-encoded message with attachments. "
            "If you see this message, your mail client is not "
            "capable of displaying the attachments.")
        if KdeQt.isKDE():
            msgtext = ("%s\r\n----\r\nVersion Numbers:\r\n  Python %s\r\n" + \
                "  KDE %s\r\n  PyKDE %s\r\n  Qt %s\r\n" + \
                "  PyQt %s\r\n  sip %s\r\n  QScintilla %s\r\n  %s %s\r\n" + \
                "  Bicycle Repair Man %s\r\n\r\nPlatform: %s\r\n%s\r\n") % \
                (unicode(self.message.text()), sys.version.split()[0],
                str(KdeQt.kdeVersionString()), str(KdeQt.pyKdeVersionString()),
                str(QT_VERSION_STR), str(PYQT_VERSION_STR), str(sip_version_str),
                str(QSCINTILLA_VERSION_STR),
                Program, Version, BRM_VERSION_STR, sys.platform, sys.version)
        else:
            msgtext = ("%s\r\n----\r\nVersion Numbers:\r\n  Python %s\r\n  Qt %s\r\n" + \
                "  PyQt %s\r\n  sip %s\r\n  QScintilla %s\r\n  %s %s\r\n" + \
                "  Bicycle Repair Man %s\r\n\r\nPlatform: %s\r\n%s\r\n") % \
                (unicode(self.message.text()), sys.version.split()[0],
                str(QT_VERSION_STR), str(PYQT_VERSION_STR), str(sip_version_str),
                str(QSCINTILLA_VERSION_STR),
                Program, Version, BRM_VERSION_STR, sys.platform, sys.version)
        
        # first part of multipart mail explains format
        msg = MIMEMultipart()
        msg['From']    = unicode(Preferences.getUser("Email"))
        msg['To']      = BugAddress
        msg['Subject'] = '[eric3] %s' % unicode(self.subject.text())
        msg.preamble = mpPreamble
        msg.epilogue = ''
        
        # second part is intended to be read
        att = MIMEText(msgtext, _charset = sys.getdefaultencoding())
        msg.attach(att)
        
        # next parts contain the attachments
        itm = self.attachments.firstChild()
        while itm:
            maintype, subtype = str(itm.text(1)).split('/', 1)
            fname = unicode(itm.text(0))
            name = os.path.basename(fname)
            
            if maintype == 'text':
                att = MIMEText(open(fname, 'rb').read(), _subtype = subtype)
            elif maintype == 'image':
                att = MIMEImage(open(fname, 'rb').read(), _subtype = subtype)
            elif maintype == 'audio':
                att = MIMEAudio(open(fname, 'rb').read(), _subtype = subtype)
            else:
                att = MIMEBase(maintype, subtype)
                att.set_payload(open(fname, 'rb').read())
                Encoders.encode_base64(att)
            att.add_header('Content-Disposition', 'attachment', filename = fname)
            msg.attach(att)
            
            itm = itm.nextSibling()
            
        return msg.as_string()

    def sendmail(self, msg):
        """
        Private method to actually send the message.
        
        @param msg the message to be sent (string)
        @return flag indicating success (boolean)
        """
        try:
            server = smtplib.SMTP(str(Preferences.getUser("MailServer")))
            if Preferences.getUser("MailServerAuthentication"):
                # mail server needs authentication
                password = str(Preferences.getUser("MailServerPassword"))
                if not password:
                    password, ok = KQInputDialog.getText(\
                        self.trUtf8("Mail Server Password"),
                        self.trUtf8("Enter your mail server password"),
                        QLineEdit.Password)
                    if not ok:
                        # abort
                        return 0
                try:
                    server.login(str(Preferences.getUser("MailServerUser")),
                                 str(password))
                except (smtplib.SMTPException, socket.error), e:
                    res = KQMessageBox.critical(self,
                        self.trUtf8("Send bug report"),
                        self.trUtf8("""<p>Authentication failed.<br>Reason: %1</p>""")
                            .arg(str(e)),
                        self.trUtf8("&Retry"),
                        self.trUtf8("&Abort"),
                        QString.null,
                        0, -1)
                    if res == 0:
                        return self.sendmail(msg)
                    else:
                        return 0

            result = server.sendmail(str(Preferences.getUser("Email")),
                BugAddress, msg)
            server.quit()
        except (smtplib.SMTPException, socket.error), e:
            res = KQMessageBox.critical(self,
                self.trUtf8("Send bug report"),
                self.trUtf8("""<p>Message could not be sent.<br>Reason: %1</p>""")
                    .arg(str(e)),
                self.trUtf8("&Retry"),
                self.trUtf8("&Abort"),
                QString.null,
                0, -1)
            if res == 0:
                return self.sendmail(msg)
            else:
                return 0
        return 1
        
    def handleAdd(self):
        """
        Private slot to handle the Add... button.
        """
        fname = KQFileDialog.getOpenFileName(\
            QString.null,
            QString.null,
            self, None,
            self.trUtf8("Attach file"),
            None, 1)
        if not fname.isEmpty():
            fname = unicode(fname)
            type = mimetypes.guess_type(fname)[0]
            if not type:
                type = "application/octet-stream"
            itm = QListViewItem(self.attachments, fname, type)
            
    def handleDelete(self):
        """
        Private slot to handle the Delete button.
        """
        itm = self.attachments.selectedItem()
        if itm is not None:
            self.attachments.takeItem(itm)
            del itm

