#!/usr/bin/env python3

import logging
from sendmail import sendmail
import datetime
import mailbox
import email
import report
from bot import Bot
from config import config
from db import db

logger = logging.getLogger(__name__)


class Mailbot(Bot):

    # returns a list of Report objects
    def crawl(self, user):
        reports = []
        # todo: adjust to actual mailbox
        try:
            mails = mailbox.mbox("/var/mail/" + config['mail']['mbox_user'])
        except FileNotFoundError:
            logger.error("No mbox file found.")
            return reports
        for msg in mails:
            if get_date_from_header(msg['Date']) > user.get_seen_mail():
                if user.get_city().lower() in msg['To'].lower():
                    reports.append(make_report(msg, user))
        return reports

    # post/boost Report object
    def post(self, user, report):
        recipients = user.get_mailinglist()
        for rec in recipients:
            rec = rec[0]
            unsubscribe_text = "\n_______\nYou don't want to receive those messages? Unsubscribe with this link: "
            body = report.text + unsubscribe_text + config['web']['host'] + "/city/mail/unsubscribe/" \
                   + db.mail_subscription_token(rec, user.get_city())
            if rec not in report.author:
                try:
                    city = user.get_city()
                    sendmail(rec, "Ticketfrei " + city + " Report",
                                      city=city, body=body)
                except Exception:
                    logger.error("Sending Mail failed.", exc_info=True)


def make_report(msg, user):
    """
    generates a report out of a mail

    :param msg: email.parser.Message object
    :return: post: report.Report object
    """
    # get a comparable date out of the email
    date = get_date_from_header(msg['Date'])

    author = msg['From']  # get mail author from email header

    if msg.is_multipart():
        text = []
        for part in msg.get_payload():
            if part.get_content_type() == "text":
                text.append(part.get_payload())
            elif part.get_content_type() == "application/pgp-signature":
                pass  # ignore PGP signatures
            elif part.get_content_type() == "multipart/mixed":
                for p in part:
                    if isinstance(p, str):
                        text.append(p)
                    elif p.get_content_type() == "text":
                        text.append(part.get_payload())
                    else:
                        logger.error("unknown MIMEtype: " +
                                     p.get_content_type())
            else:
                logger.error("unknown MIMEtype: " +
                             part.get_content_type())
        text = '\n'.join(text)
    else:
        text = msg.get_payload()
    post = report.Report(author, "mail", text, None, date)
    user.save_seen_mail(date)
    return post


def get_date_from_header(header):
    """
    :param header: msg['Date']
    :return: float: total seconds
    """
    date_tuple = email.utils.parsedate_tz(header)
    date_tuple = datetime.datetime.fromtimestamp(
        email.utils.mktime_tz(date_tuple)
    )
    return (date_tuple - datetime.datetime(1970, 1, 1)).total_seconds()