package com.workfusion.odf.impl.connector;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import javax.inject.Inject;
import javax.inject.Named;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;

import com.workfusion.odf.api.connector.TransactionSupplier;
import com.workfusion.odf.api.domain.Transaction;
import com.workfusion.odf.service.mail.util.EmailParsingUtils;
import com.workfusion.odf.service.mail.EmailManager;
import com.workfusion.odf.service.mail.entity.EmailMessage;
import com.workfusion.rpa.core.storage.S3Manager;

public class EmailTransactionConnector implements TransactionSupplier {

    private final S3Manager s3Manager;
    private final EmailManager emailManager;
    private final EmailSettings settings;
    private final Logger logger;

    @Inject
    public EmailTransactionConnector(S3Manager s3Manager, Logger logger, EmailManager emailManager,
            @Named("botConfigParams") Map<String, String> params) {
        this.s3Manager = s3Manager;
        this.settings = new EmailSettings(params);
        this.emailManager = emailManager;
        this.logger = logger;
    }

    @Override
    public Collection<Transaction> get() {
        logger.info("Getting unread messages");
    	List<EmailMessage> emailMessages = fetchEmails();
        logger.info("Got {} unread messages", emailMessages.size());

        List<Transaction> transactions = emailMessages.stream()
                .map(this::convertMessageToTransaction)
                .collect(Collectors.toList());


        String postAction = settings.getPostAction();
        final String targetFolder = settings.getTargetFolder();
        if ("copy".equals(postAction)) {
            logger.info("Copying messages to {}", targetFolder);
            copyEmails(emailMessages, targetFolder);
        } else if ("move".equals(postAction)) {
            logger.info("Moving messages to {}", targetFolder);
            moveEmails(emailMessages, targetFolder);
        }

        return transactions;
    }

    private void copyEmails(List<EmailMessage> emailMessages, String targetFolder) {
        emailMessages.forEach(msg -> emailManager.copyMessage(msg, targetFolder));
    }

    private void moveEmails(List<EmailMessage> emailMessages, String targetFolder) {
        emailMessages.forEach(msg -> emailManager.moveMessage(msg, targetFolder));
    }

    private List<EmailMessage> fetchEmails() {
    	String inputFolder = settings.getInputFolder();
        if (StringUtils.isEmpty(inputFolder)) {
        	return emailManager.fetchUnreadMessages(settings.markAsRead());
        } else {
        	return emailManager.fetchUnreadMessages(inputFolder, settings.markAsRead());
        }
	}

	private Transaction convertMessageToTransaction(EmailMessage message) {
        String s3Folder = settings.getS3Folder();
        return EmailParsingUtils.convertMessageToTransaction(message, s3Manager, s3Folder);
    }

    /**
     * Email Connector settings:
     *   - Input folder name
     *   - 'Mark as read' flag
     */
    public static final class EmailSettings {

    	public static final String PARAM_INBOX_FOLDER = "input_folder";
        public static final String PARAM_MARK_AS_READ = "mark_as_read";
        public static final String PARAM_POST_ACTION = "post_action";
        public static final String PARAM_TARGET_FOLDER = "target_folder";
        public static final String MAIL_S3_FOLDER = "mail_s3_folder";

        private Map<String, String> params;

        public EmailSettings(Map<String, String> params) {
            this.params = params;
        }

        public String getInputFolder() {
            return params.get(PARAM_INBOX_FOLDER);
        }

        public boolean markAsRead() {
            return Boolean.parseBoolean(params.get(PARAM_MARK_AS_READ));
        }

        public String getPostAction() {
            return params.get(PARAM_POST_ACTION);
        }

        public String getTargetFolder() {
            return params.get(PARAM_TARGET_FOLDER);
        }

        public String getS3Folder() {
            return params.get(MAIL_S3_FOLDER);
        }
    }
}
