#!/usr/bin/python
# -*- coding: UTF-8 -*-
#
# Copyright (c) 2007 Tarek Ziadé
#
# Authors:
#   Tarek Ziadé <tarek@ziade.org>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
from datetime import datetime
import os
import sys
import smtplib
import logging
from threading import Thread
import time
from base64 import b64decode
from email.MIMEText import MIMEText

from model import mailed_data, mail_data
import settings

class MailWorker(Thread):
    """reads the SQLDB to do the jobs"""

    def __init__(self):
        Thread.__init__(self)
        self.is_working = False
        self.running = False

    def _get_mails(self):
        """returns lines of mail_data """
        return mail_data.select().execute().fetchall()

    def _get_message(self, mail):
        """returns a Mime"""
        data = b64decode(mail.data)
        # some sgbd are in unicode
        if isinstance(data, unicode):
            data = data.decode('utf8')
        msg = MIMEText(data)
        msg['From'] = mail.sender
        msg['To'] = mail.recipients
        msg['Subject'] = mail.subject
        msg.set_charset('utf-8')
        msg['Date'] = mail.date.strftime('%c')
        return msg

    def _send_mail(self, mail):
        """sends the mail"""
        server = smtplib.SMTP(settings.SMTP_SERVER)
        msg = self._get_message(mail)
        try:
            server.sendmail(msg['From'], msg['To'], msg.as_string())
        finally:
            server.quit()
        logging.debug('mailer:message sent to %s' % msg['To'])

    def _store_mail(self, mail, error=None):
        """stores the mail"""
        if error is not None:
            error = str(error)
        ins = mailed_data.insert()
        ins.execute(subject=mail.subject, sender=mail.sender,
                    original_id=mail.id, recipients=mail.recipients,
                    error=error, data=mail.data, date=datetime.now(),
                    status='processed')

        # removes from original table
        mail_data.delete().execute(id=mail.id)

    def run(self):
        """called threaded"""
        self.running = True
        logging.debug('mailer:launched')

        while self.running:
            # index
            self.is_working = True
            try:
                # get mails to send
                mails = self._get_mails()
                for mail in mails:
                    try:
                        # send then
                        self._send_mail(mail)
                    except Exception, e:
                        logging.debug('mailer:failed to send mail')
                        self._store_mail(mail, e)
                    else:
                        self._store_mail(mail)
            finally:
                self.is_working = False
                time.sleep(.1)

        logging.debug('mailer:stopped')

worker = None

def start_server():
    """starts the worker"""
    global worker
    worker = MailWorker()
    worker.start()

def stop_server():
    """stops the worker"""
    global worker
    if worker is not None:
        worker.running = False
        worker.join()
        worker = None

def is_working():
    """tells if the worker works"""
    return worker.is_working

# will make sure the thread stops when the process quits
from atexit import register
register(stop_server)

