package com.avaya.customer.example.servlet.utils;

import com.avaya.customer.example.servlet.api.ChatMessage;
import com.avaya.customer.example.servlet.api.EmailTranscript;
import com.avaya.customer.example.servlet.api.MessageTranscriptV1;
import com.avaya.customer.example.servlet.api.MessageTranscriptV2;
import com.avaya.customer.example.servlet.api.MessageType;
import com.avaya.customer.example.servlet.api.TranscriptContext;
import com.avaya.customer.example.servlet.api.TranscriptContextAndMessage;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.type.TypeReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import static com.avaya.customer.example.servlet.ContextListener.appConfig;
import static com.avaya.customer.example.servlet.utils.Constants.emailTranscriptsDir;
import static com.avaya.customer.example.servlet.utils.Constants.messagingTranscriptsDir;

/**
 * Contains methods for saving transcripts, downloading attachments.
 */
public class FileUtils {

    private static final Logger LOG = LoggerFactory.getLogger(FileUtils.class);
    private static final DownloadManager downloadManager = new DownloadManager();
    private static final ObjectMapper MAPPER = new ObjectMapper();
    private static final String DATE_FORMAT_PATTERN = "yyyy-MM-dd-HH-mm-ss";

    public static void saveEmailTranscript(EmailTranscript transcript) {
        if (appConfig.isSaveEmailTranscripts()) {
            final DateFormat TRANSCRIPT_DATE_FORMAT = new SimpleDateFormat(DATE_FORMAT_PATTERN);
            String filename = null;

            if (transcript.getWorkRequestId() != null && !transcript.getWorkRequestId().isEmpty()) {
                filename = transcript.getWorkRequestId();
            } else if (transcript.getTimestamp() != null) {
                filename = TRANSCRIPT_DATE_FORMAT.format(new Date(transcript.getTimestamp()));

                if ("outgoing".equalsIgnoreCase(transcript.getDirection())) {
                    filename = "adhoc-" + filename;
                }
            }

            String filePath = emailTranscriptsDir + filename;

            List<EmailTranscript> transcriptToSave = new ArrayList<>();
            transcriptToSave.add(transcript);

            saveToFile(transcriptToSave, filePath + ".json");

            if (appConfig.isDownloadAttachments()) {
                List<String> attachments = transcript.getAttachments();
                if (attachments != null && !attachments.isEmpty()) {
                    downloadManager.downloadAttachments(transcript, filePath);
                } else {
                    LOG.info("No attachments to download");
                }
            } else {
                LOG.info("Attachments downloading is disabled");
            }
        } else {
            LOG.info("Email transcripts saving is disabled");
        }
    }

    public static void saveMessageTranscript(List<MessageTranscriptV1> transcript) {
        if (appConfig.isSaveMessageTranscripts()) {
            String wrid = transcript.isEmpty() ? "empty" : transcript.get(0).getWorkRequestId();
            String filePath = messagingTranscriptsDir + wrid;
            saveToFile(transcript, filePath + ".json");

            if (appConfig.isDownloadAttachments()) {
                for (MessageTranscriptV1 message : transcript) {
                    if (message.getMessageType() == MessageType.FILETRANSFER) {
                        downloadManager.downloadAttachments(message, filePath);
                    }
                }
            } else {
                LOG.info("Attachments downloading is disabled");
            }
        } else {
            LOG.info("Messaging transcripts saving is disabled");
        }
    }

    public static void saveTranscriptAndContext(TranscriptContextAndMessage transcript) {
        if (appConfig.isSaveMessageTranscripts()) {
            String wrid = transcript.getTranscriptContext().getWorkRequestId().isEmpty() ? "empty" :
                    transcript.getTranscriptContext().getWorkRequestId();
            String filePath = messagingTranscriptsDir + wrid;
            saveToFile(transcript, filePath + ".json");

            if (appConfig.isDownloadAttachments()) {
                for (MessageTranscriptV2 message : transcript.getTranscriptMessages()) {
                    if (message.isAsyncFile()) {
                        downloadManager.downloadAttachments(message, filePath);
                    }
                }
            } else {
                LOG.info("Attachments downloading is disabled");
            }
        } else {
            LOG.info("Messaging transcripts saving is disabled");
        }
    }

    public static void saveChatTranscript(List<ChatMessage> transcript) {

        if (appConfig.isSaveChatTranscripts()) {
            String date = transcript.isEmpty() ? "empty"
                    : String.valueOf(transcript.get(0).getDate());
            String filePath = messagingTranscriptsDir + date + ".json";
            saveToFile(transcript, filePath);
            if (appConfig.isDownloadAttachments()) {
                for (ChatMessage message : transcript) {
                    if (message.getMessageType() == MessageType.FILETRANSFER) {
                        downloadManager.downloadAttachments(message, filePath);
                    }
                }
            } else {
                LOG.info("Attachments downloading is disabled");
            }
        } else {
            LOG.info("Chat transcripts saving is disabled");
        }
    }

    private static void saveToFile(List<?> newTranscripts, String filePath) {
        File file = new File(filePath);
        file.getParentFile().mkdirs();
        try {

            // Read in any existing transcripts in this file, if present, otherwise start with a new list
            List<Object> transcriptsToWrite;
            if (file.exists()) {
                transcriptsToWrite = MAPPER.readValue(file, new TypeReference<List<Object>>() {});
            } else {
                transcriptsToWrite = new ArrayList<>();
            }

            transcriptsToWrite.addAll(newTranscripts);

            MAPPER.writerWithDefaultPrettyPrinter().writeValue(file, transcriptsToWrite);
            LOG.info("Transcript saved in file: " + filePath);
        } catch (IOException ioe) {
            LOG.error("Unable to save transcript to file [" + filePath + "]", ioe);
        }
    }

    private static void saveToFile(TranscriptContextAndMessage transcriptContextAndMessage, String filePath) {
        File file = new File(filePath);
        file.getParentFile().mkdirs();
        try {

            // Read in any existing transcripts in this file, if present, otherwise start with a new list
            TranscriptContextAndMessage transcriptsToWrite;
            if (file.exists()) {
                transcriptsToWrite = MAPPER.readValue(file, new TypeReference<TranscriptContextAndMessage>() {});
            } else {
                transcriptsToWrite = new TranscriptContextAndMessage(new TranscriptContext(), new ArrayList<>());
            }

            transcriptsToWrite.setTranscriptContext(transcriptContextAndMessage.getTranscriptContext());
            transcriptsToWrite.getTranscriptMessages().addAll(transcriptContextAndMessage.getTranscriptMessages());

            MAPPER.writerWithDefaultPrettyPrinter().writeValue(file, transcriptsToWrite);
            LOG.info("Transcript and Context saved in file: " + filePath);
        } catch (IOException ioe) {
            LOG.error("Unable to save transcript to file [" + filePath + "]", ioe);
        }
    }
}
