from pathlib import Path
import datetime
import re
import os
import win32com.client  #pip install pywin32

import cv2
import pytesseract
import numpy as np
import requests
import pdfplumber

from main import *
import image_processing
from pynput import keyboard


#-----------------------------
"""
import win32com.client as win32
excel = win32.gencache.EnsureDispatch('MailAnd.Application')

excel.Visible = True
_ = input("Press ENTER to quit:")

excel.Application.Quit()
"""
#--------------------------

# Carpeta d'input per descarregar els missatges
input_dir = Path.cwd() / "Input"
input_dir.mkdir(parents=True, exist_ok=True)

counts = {0:'DR',1:'F',2:'FD',3:'IT',4:'NS',5:'TG'}

# Estructura del missatge a enviar
MESSAGE_TO_SEND = {0:"",1:"",2:"",3:[]}
# 0=To, 1=Subject, 2=Body, 3=Attachments


# Funció per processar imatges a text
def image_to_text(filepath):
    text = ""
    # OCR HERE
    img = cv2.imread(filepath)
    text = image_processing.process(img)
    return text


# Funció per a convertir pdfs a text
def pdf_to_text(filepath):
    text = ""
    with pdfplumber.open(filepath) as pdf:
        for i in range(0,len(pdf.pages)):
            page = pdf.pages[i]
            text_process = page.extract_text()
            text += text_process
    if text == "":
        return image_to_text(filepath)
    else:
        return text


# Funció per convertir fitxers txt a text
def text_to_text(filepath):
    text = ""
    if filepath.endswith(('EMAIL_BODY.txt')):
        return text
    else:
        with open(filepath, 'r') as file:
            text = file.read()
        return text


# Funció genèrica per classificar diferents tipus de fitxers i cridar a la funció filla pertinent
def file_to_text(filepath):
    if filepath.lower().endswith(('.pdf')):
        return pdf_to_text(filepath)
    elif filepath.lower().endswith(('.png')) or filepath.lower().endswith(('.jpg')):
        return image_to_text(filepath)
    elif filepath.lower().endswith(('.txt')):
        return text_to_text(filepath)


# Funció per processar els fitxers compresos en un mateix correu
def process(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 = file_to_text(f)
            if text != "":
                final_text += text
    return final_text


# Funció per resetejar el missatge a enviar
def reset_message_to_send():
    MESSAGE_TO_SEND = {0: "", 1: "", 2: "", 3: []}
    # 0=To, 1=Subject, 2=Body, 3=Attachments


# Funció per compondre i enviar el missatge de resposta a partir de la classificació
def send_message(label):
    outlook = win32com.client.dynamic.Dispatch("Outlook.Application")
    mail = outlook.CreateItem(0)

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

    # Check all needed values are valid
    if destinatary and subject and attachments_list != []:
        # 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()
            reset_message_to_send()
            return "Email sent succesfully"
        except:
            return "Email was not sent"
    else:
        return "Missing something to send email"


# Funció per obtenir la safata d'entrada del correu
def get_message():
    print("Waiting for input...")
    # Connect to outlook
    outlook = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI")

    # Connect to folder
    inbox = outlook.Folders("testing2023tfg@outlook.com").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_recieved_date = str(message.ReceivedTime.strftime('%d-%m-%Y_%H-%M-%S'))

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

        # Create separate folder for each message, exclude special characters and timestampe
        current_time = datetime.datetime.now().strftime("%d/%m/%Y_%H:%M:%S")
        target_folder = input_dir / email_recieved_date / email_sender / re.sub('[^0-9a-zA-Z]+', '', subject)

        if os.path.exists(target_folder):
            pass
        else:
            MESSAGE_TO_SEND[0] = email_sender
            MESSAGE_TO_SEND[1] = subject
            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)
                MESSAGE_TO_SEND[3].append(str(target_folder) + "/" + str(filename))

                # Process call
            print(MESSAGE_TO_SEND)
            text = process(target_folder)
            if text != "":
                list.append(text)
    return list


break_execution = False

# Funció per interrompre l'execució
def on_press(key):
    global break_execution
    if key == keyboard.Key.end:
        break_execution = True
        return False

# Funció main per a executar i testejar les diferents funcionalitats
if __name__ == '__main__':
        text_list = get_message()
        if text_list != []:
            for item in text_list:
                print(type(item))
                label = classify_deep([item])
                print(send_message(counts[label[0]]))
    #print(send_message("FD"))



