
import win32com.client
import datetime
from pathlib import Path
import re
import os
from TextConverter import TextConverter
from datetime import datetime


class EmailService:

    def __init__(self, input_mail, white_list, output_mail_list, categories, mail_categorization):
        print("Email Service object created")
        self.input_mail = input_mail
        self.white_list = white_list
        self.output_mail_list = output_mail_list
        self.categories = categories
        self.mail_categorization = mail_categorization

        self.input_dir = Path.cwd() / "Input"
        self.input_dir.mkdir(parents=True, exist_ok=True)

        self.MESSAGE_TO_SEND = {0:"",1:"",2:"",3:[]}
        # 0=To, 1=Subject, 2=Body, 3=Attachments

        self.converter = TextConverter()

        # Todo debug a un fitxer txt
        self.debug = False
        self.debug_path = Path.cwd() / "Log/AutoMailClassifier/LogAutoMailClassifier.txt"

        self.limit_days = 1


    def enable_disable_log_debugging(self, enable):
        self.debug = enable
        current_time = datetime.now().strftime("%Y/%d/%m_%H:%M:%S")
        if not os.path.isfile(self.debug_path):
            target_folder = Path.cwd() / "Log/AutoMailClassifier"
            if not os.path.exists(target_folder):
                os.makedirs(target_folder)
                f = open(self.debug_path, "x")
                f.write(current_time + " : " + "Email Service - Debug Logging enabled = " + str(enable) + "\n")
            else:
                f = open(self.debug_path, "w")
                f.write(current_time + " : " + "Email Service - Debug Logging enabled = " + str(enable) + "\n")
        else:
            f = open(self.debug_path, "a")
            f.write(current_time + " : " + "Email Service - Debug Logging enabled = " + str(enable) + "\n")
        f.close()
        self.converter.enable_disable_log_debugging(enable)


    def get_messages(self):
        # Connect to outlook
        outlook = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI")

        current_time = datetime.now().strftime("%Y/%d/%m_%H:%M:%S")

        if self.debug:
            f = open(self.debug_path, "a")
            f.write(current_time + " : " + "Email Service - Getting messages...\n")
            f.close()

        # Connect to folder
        inbox = outlook.Folders(self.input_mail).Folders("Inbox")
        # inbox = outlook.GetDefaultFolder(6)
        # https://docs.microsoft.com/en-us/office/vba/api/outlook.oldefaultfolders
        # DeletedItems=3, Outbox=4, SentMail=5, Inbox=6, Drafts=16, FolderJunk=23

        # Get messages
        messages = inbox.Items
        list = []
        for message in messages:
            subject = message.Subject
            body = message.body
            attachments = message.Attachments
            if message.Class == 43:
                if message.SenderEmailType == 'EX':
                    email_sender = str(message.Sender.GetExchangeUser().PrimarySmtpAddress)
                else:
                    email_sender = str(message.SenderEmailAddress)
                email_received_date = str(message.ReceivedTime.strftime('%d-%m-%Y_%H-%M-%S'))
                formated_email_received_date = str(message.ReceivedTime.strftime('%d-%m-%Y'))
                formated_current_time = datetime.now().strftime('%d-%m-%Y')
                d1 = datetime.strptime(formated_email_received_date, '%d-%m-%Y')
                d2 = datetime.strptime(formated_current_time, '%d-%m-%Y')

            if subject == "":
                subject = "subject"
            if body == "":
                body = "body"

            delta = d2 - d1
            if int(delta.days) <= self.limit_days:
                # Create separate folder for each message, exclude special characters and timestampe
                target_folder = self.input_dir / email_received_date / email_sender / re.sub('[^0-9a-zA-Z]+', '', subject)

                if os.path.exists(target_folder):
                    pass
                else:
                    if email_sender in self.white_list:
                        if self.debug:
                            f = open(self.debug_path, "a")
                            f.write(current_time + " : " + "Email Service - Processing input -> Date= " + str(email_received_date) + ", Email Sender= " + str(email_sender) + ", Subject= " + str(subject) + ", Attachments= " + str(len(attachments)) + "\n")
                            f.close()
                        if self.mail_categorization:
                            self.MESSAGE_TO_SEND[1] = subject
                            self.MESSAGE_TO_SEND[2] = body

                            target_folder.mkdir(parents=True, exist_ok=True)
                            # Write body to text file
                            Path(target_folder / "EMAIL_BODY.txt").write_text(str(body))
                            # Save attachments and exclude special
                            for attachment in attachments:
                                filename = re.sub('[^0-9a-zA-Z\.]+', '', attachment.FileName)
                                attachment.SaveAsFile(target_folder / filename)
                                self.MESSAGE_TO_SEND[3].append(str(target_folder) + "/" + str(filename))

                            text = self.process(target_folder)
                            if text != "":
                                list.append(text)
                        else:
                            self.MESSAGE_TO_SEND[0] = email_sender
                            self.MESSAGE_TO_SEND[1] = subject
                            self.MESSAGE_TO_SEND[2] = body

                            target_folder.mkdir(parents=True, exist_ok=True)
                            # Write body to text file
                            Path(target_folder / "EMAIL_BODY.txt").write_text(str(body))
                            # Save attachments and exclude special
                            for attachment in attachments:
                                filename = re.sub('[^0-9a-zA-Z\.]+', '', attachment.FileName)
                                attachment.SaveAsFile(target_folder / filename)
                                self.MESSAGE_TO_SEND[3].append(str(target_folder) + "/" + str(filename))

                            text = self.process(target_folder)
                            if text != "":
                                if self.debug:
                                    f = open(self.debug_path, "a")
                                    f.write(current_time + " : " + "Email Service - Returning non empty text\n")
                                    f.close()
                                list.append(text)
                            else:
                                if self.debug:
                                    f = open(self.debug_path, "a")
                                    f.write(current_time + " : " + "Email Service - Returning empty text\n")
                                    f.close()
                    else:
                        pass
            else:
                pass
        return list


    def process(self, target_folder):
        final_text = ""
        for filename in os.listdir(target_folder):
            f = os.path.join(target_folder, filename)
            # checking if it is a file
            if os.path.isfile(f):
                text = self.converter.file_to_text(f)
                if text != "":
                    final_text += str(text)
        return final_text


    def reset_message_to_send(self):
        self.MESSAGE_TO_SEND = {0: "", 1: "", 2: "", 3: []}
        current_time = datetime.now().strftime("%Y/%d/%m_%H:%M:%S")
        if self.debug:
            f = open(self.debug_path, "a")
            f.write(current_time + " : " + "Email Service - Resetting message to send\n")
            f.close()
        # 0=To, 1=Subject, 2=Body, 3=Attachments


    def send_message(self, label):
        current_time = datetime.now().strftime("%Y/%d/%m_%H:%M:%S")

        outlook = win32com.client.dynamic.Dispatch("Outlook.Application")
        mail = outlook.CreateItem(0)

        # Gather that information and asign to variable
        destinatary = str(self.MESSAGE_TO_SEND[0])
        subject = str(self.MESSAGE_TO_SEND[1])
        # The subject will now contain the label
        if self.mail_categorization == False:
            subject += " - " + label
        body = str(self.MESSAGE_TO_SEND[2])
        attachments_list = self.MESSAGE_TO_SEND[3]

        # Check all needed values are valid
        if subject and attachments_list != []:
            if self.mail_categorization and self.MESSAGE_TO_SEND[0] == "":
                # Meaning destinatary should be empty:
                mail.To = self.output_mail_list[label]
                mail.Subject = subject
                mail.Body = body
                # To attach files to the email:
                for item in attachments_list:
                    attachment = str(item)
                    mail.Attachments.Add(attachment)

                # Sending the email
                try:
                    mail.Send()
                    self.reset_message_to_send()
                    if self.debug:
                        f = open(self.debug_path, "a")
                        f.write(current_time + " : " + "Email Service - Email sent to: " + str(destinatary) + ", Subject: " + str(subject) + ", Label: " + str(label) +"\n")
                        f.close()
                    return "Email sent succesfully"
                except:
                    if self.debug:
                        f = open(self.debug_path, "a")
                        f.write(current_time + " : " + "Email Service - ERROR: Email was not sent\n")
                        f.close()
                    return "Email was not sent"
            else:
                # Asign variables
                mail.To = destinatary
                mail.Subject = subject
                mail.Body = body
                # To attach files to the email:
                for item in attachments_list:
                    attachment = str(item)
                    mail.Attachments.Add(attachment)

                # Sending the email
                try:
                    mail.Send()
                    self.reset_message_to_send()
                    if self.debug:
                        f = open(self.debug_path, "a")
                        f.write(current_time + " : " + "Email Service - Email sent to: " + str(destinatary) + ", Subject: " + str(subject) + ", Label: " + str(label) +"\n")
                        f.close()
                    return "Email sent succesfully"
                except:
                    if self.debug:
                        f = open(self.debug_path, "a")
                        f.write(current_time + " : " + "Email Service - ERROR: Email was not sent\n")
                        f.close()
                    return "Email was not sent"
        else:
            if self.debug:
                f = open(self.debug_path, "a")
                f.write(current_time + " : " + "Email Service - ERROR: Missing something to send email\n")
                f.close()
            return "Missing something to send email"

