package usda.weru.weps;

import java.awt.Dimension;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import de.schlichtherle.truezip.file.TFile;
import de.schlichtherle.truezip.file.TFileOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.Vector;
import java.util.zip.ZipOutputStream;
import javax.help.CSH;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import org.apache.log4j.Logger;
import org.jdesktop.jdic.desktop.DesktopException;
import org.jdesktop.jdic.desktop.Message;

import usda.weru.util.*;

/**
 * This class/object is used to send emails with bug reports attached or interface mis behaviour
 * messages to the WEPS support team from within the interface. Project folders and run files with
 * particular test case could be used as information.
 */
public class Email extends usda.weru.weps.gui.Email_n implements PropertyChangeListener {

    private static final long serialVersionUID = 1L;

    private static final Logger LOGGER = Logger.getLogger(Email.class);

    private String c_mailHost = "";
    private boolean c_useSmtp = true;
    private String c_toComments = "";
    private String c_toBugs = "";
    private boolean c_error = false;
    private boolean outlookFlg = false;

    private String c_projectsPath;
    private String c_runPath;

    /**
     * Default constructor for the email object/class tbat calls the parent GUI object and adds help
     * material for the GUI.
     */
    public Email() {
        super();
        addHelp();
        setTitle("WEPS Email");
        //setIconImage(wepsbIcon.getImage());

        super.setIconImage(About.getWeruIconImage());

        if (c_configData != null) {
            c_configData.addPropertyChangeListener(this);
            c_configData.fireAll(this);
        }
    }

    /**
     *
     * @param to
     * @param subject
     * @param body
     * @param attachment
     * @param error
     * @param allowAttach
     * @param autoSend
     */
    public Email(String to, String subject, String body, String attachment,
            boolean error, boolean allowAttach, boolean autoSend) {
        this();
        c_error = error;

        if (to == null || to.length() == 0) {
            if (error) {
                to = c_toBugs;
            } else {
                to = c_toComments;
            }
        }
        if (subject == null) {
            subject = "";
        }
        if (body == null) {
            body = "";
        }

        JTF_subject.setText(subject);
        JTF_attachment.setText(attachment);
        JTF_to.setText(to);
        JTA_text.setText(body);

        autoSend = autoSend || (c_error && !c_useSmtp) || (!allowAttach && !c_useSmtp);

        if (autoSend) {
            if (c_useSmtp) {
                JB_send.doClick();
            } else {
                JB_client.doClick();
            }
            dispose();
        } else {
            JB_Run.setVisible(allowAttach);
            JB_Project.setVisible(allowAttach);
            JTF_attachment.setEnabled(allowAttach);

            setVisible(true);
        }
    }

    /**
     *
     */
    public static void blank() {
        comment(null, null, null);
    }

    /**
     *
     * @param subject
     * @param body
     * @param attachment
     */
    public static void comment(String subject, String body, String attachment) {
        boolean allowAttach = attachment == null || attachment.length() == 0;
        new Email(null, subject, body, attachment, false, allowAttach, false);
    }

    /**
     *
     * @param subject
     * @param body
     * @param attachment
     */
    public static void error(String subject, String body, String attachment) {
        boolean allowAttach = attachment == null || attachment.length() == 0;
        new Email(null, subject, body, attachment, true, allowAttach, false);
    }

    /**
     * help stuff
     */
    private void addHelp() {

        CSH.setHelpIDString(JL_to, "emailTo_html");
        CSH.setHelpIDString(JTF_to, "emailTo_html");
        CSH.setHelpIDString(JL_from, "emailFrom_html");
        CSH.setHelpIDString(JTF_from, "emailFrom_html");
        CSH.setHelpIDString(JL_subject, "emailSubject_html");
        CSH.setHelpIDString(JTF_subject, "emailSubject_html");
        CSH.setHelpIDString(JL_attachment, "emailAttachment_html");
        CSH.setHelpIDString(JTF_attachment, "emailAttachment_html");

        CSH.setHelpIDString(JSP_text, "emailComments_html");
        CSH.setHelpIDString(JP_buttons, "emailButtons_html");
        CSH.setHelpIDString(this, "emailScreen_html");

        /*CSH.setHelpIDString(JB_send, "emailSendButton");
         CSH.setHelpIDString(JB_cancel, "emailCancelButton");
         CSH.setHelpIDString(JB_Run, "emailAttachRunButton");
         CSH.setHelpIDString(JB_Project, "emailAttachProjButton");*/
    }

    /**
     * This method notifies when the window or frame is resized and the components need to be re-arranged
     * so they are evenly spaced relative to each other.
     * @param args Command line arguments passed that are needed if it were a stand alone application.
     */
    static public void main(String args[]) {
        //TODO: basic starter
    }

    @SuppressWarnings("unchecked")
    @Override
    public void JBSend_actionPerformed(java.awt.event.ActionEvent event) {
        String sendTo = JTF_to.getText();
        if (sendTo.length() == 0) {
            JOptionPane.showMessageDialog(this,
                    "Recipient not specified.\nAborting send",
                    "Error (E-002)",
                    JOptionPane.WARNING_MESSAGE);
            return;
        }
        String sentFrom = JTF_from.getText();
        if (sentFrom.length() == 0) {
            JOptionPane.showMessageDialog(this,
                    "Sender not specified.\nAborting send",
                    "Error (E-003)",
                    JOptionPane.WARNING_MESSAGE);
            return;
        }

        String subject = JTF_subject.getText();
        if (subject.length() == 0) {
            subject = JTF_attachment.getText();
        }

        String messageText = JTA_text.getText();
        if (messageText.length() == 0) {
            messageText = "no message";
        }

        TFile attachment = null;
        Vector<TFile> attachments = new Vector<>();
        String attachPath = JTF_attachment.getText().trim();
        if (attachPath == null) {
        } else if (attachPath.trim().length() == 0) {
        } else if (!(new TFile(attachPath).exists())) {
            JOptionPane.showMessageDialog(this,
                    "Attachment file not found\nAborting send",
                    "Error (E-001)",
                    JOptionPane.WARNING_MESSAGE);
            return;
        } else {
            attachment = new TFile(makeZipFile(attachPath));
            attachments.add(attachment);
        }

        try {
            Mailer.sendMail(c_mailHost,
                    sentFrom, sendTo, subject, messageText,
                    attachments);
        } catch (java.io.IOException | javax.mail.internet.AddressException e) {
            JOptionPane.showMessageDialog(this, e,
                    "Error -- Mail not sent",
                    JOptionPane.WARNING_MESSAGE);
            return;
        } catch (javax.mail.MessagingException g) {
            JOptionPane.showMessageDialog(this, g,
                    "Error -- Mail not sent",
                    JOptionPane.WARNING_MESSAGE);
        } finally {
            if (attachment != null) {
                attachment.deleteOnExit();
            }
        }

        try {
            this.dispose();
        } catch (java.lang.Exception e) {
        }
    }

    /**
     *
     * @param evt
     */
    @Override
    protected void JB_client_actionPerformed(java.awt.event.ActionEvent evt) {
        List<String> recipients = new Vector<String>();
        List<String> attachments = new Vector<String>();

        //Recipients
        String to = JTF_to.getText();
        if (outlookFlg) {
            if (!to.startsWith("smtp:")) {
                to = "smtp:" + to;
            }
        }
        recipients.add(to);

        //Attachments
        String attachPath = JTF_attachment.getText().trim();
        if (attachPath == null) {
        } else if (attachPath.trim().length() == 0) {
        } else if (!(new TFile(attachPath).exists())) {
            JOptionPane.showMessageDialog(this,
                    "Attachment file not found",
                    "Error (E-001)",
                    JOptionPane.WARNING_MESSAGE);
            return;
        } else {
            attachments.add(makeZipFile(attachPath).getAbsolutePath());
        }

        try {
            Message msg = new Message();
            msg.setToAddrs(recipients);
            msg.setAttachments(attachments);
            msg.setSubject(JTF_subject.getText());

            //TODO: Figure out how to set the mime-type to html so the body is displayed correctly
            //msg.setBody(JTA_text.getText());            
            org.jdesktop.jdic.desktop.Desktop.mail(msg);
        } catch (UnsatisfiedLinkError | NoClassDefFoundError ule) {
            LOGGER.error("The required system JDIC stub is missing from the java class path.", ule);
            JOptionPane.showMessageDialog(this, "The required system JDIC stub is missing from the java class path.",
                    "Error -- Unable to open default mail client", JOptionPane.WARNING_MESSAGE);
            return;
        } catch (IOException | DesktopException e) {
            LOGGER.error("Unable to open default mail client", e);
            JOptionPane.showMessageDialog(this, e, "Error -- Unable to open default mail client", JOptionPane.WARNING_MESSAGE);
            return;
        }

        try {
            dispose();
        } catch (java.lang.Exception e) {
        }
    }

    /**
     *
     * @param pathName
     * @return
     */
    public java.io.File makeZipFile(String pathName) {
        java.io.File zipFile = null;
        try {
            java.io.File tempDir = java.io.File.createTempFile("WEPS", null).getParentFile();

            java.io.File input = new java.io.File(pathName);
            String filename = input.getName();

            if (!c_error) {
                zipFile = new TFile(tempDir, filename + ".zip");
            } else {
                zipFile = new TFile(tempDir, filename + "_crash.zip");
            }

            TFileOutputStream os = new TFileOutputStream(zipFile);
            try (ZipOutputStream zip_os = new ZipOutputStream(os)) {
                TFile logFile = About.getLog();

                if (logFile != null && logFile.exists()) {
                    Util.writeFileToZip(zip_os, logFile, filename);
                }
                Util.writeFileToZip(zip_os, new TFile("cfg", "weps.cfg"), filename);
                if (input.isDirectory()) {
                    Util.writeDirToZip(zip_os, input, filename);
                } else {
                    Util.writeFileToZip(zip_os, input, filename);
                }
            }

        } catch (IOException e) {
            LOGGER.error("Unable to make zip file", e);
        }
        return zipFile;
    }

    @Override
    public void JBCancel_actionPerformed(java.awt.event.ActionEvent event) {
        try {
            this.dispose();
        } catch (java.lang.Exception e) {
        }

    }

    @Override
    public void JBRun_actionPerformed(java.awt.event.ActionEvent event) {
        WepsFileChooser wpc = new WepsFileChooser(WepsFileChooser.Filetype.RUN, c_runPath,
                WepsFileChooser.SELECT);
        wpc.setCurrentDirectory(new de.schlichtherle.truezip.file.TFile(
                (new de.schlichtherle.truezip.file.TFile(c_runPath)).getPath()));
        //set the tooltip of "home" button to "Home" instead of "Desktop"
        wpc.homeToolTip(wpc);
        //remove the NewFolder button
        wpc.disableNewFolder(wpc);

        if (wpc.showDialog(this) == JFileChooser.APPROVE_OPTION) {
            JTF_attachment.setText(wpc.getSelectedFile().getPath());
        }
    }

    @Override
    public void JBProject_actionPerformed(java.awt.event.ActionEvent event) {
        WepsFileChooser wpc = new WepsFileChooser(WepsFileChooser.Filetype.PROJECT, c_projectsPath,
                WepsFileChooser.SELECT);
        wpc.setCurrentDirectory(new TFile((new TFile(c_projectsPath)).getPath()));
        //set the tooltip of "home" button to "Home" instead of "Desktop"
        wpc.homeToolTip(wpc);
        //remove the NewFolder button
        wpc.disableNewFolder(wpc);

        if (wpc.showDialog(this) == JFileChooser.APPROVE_OPTION) {
            String attachedFile = null;
            attachedFile = wpc.getSelectedFile().getPath();
            JTF_attachment.setText(attachedFile);
        }
    }

    /**
     * The method that gets called when any changes to the registered property happen
     * whose new vales need to be propagaed and updated so as to reflect the most current data.
     * @param e The event that occurs on the property.
     */
    @Override
    public void propertyChange(PropertyChangeEvent e) {
        String property = e.getPropertyName();
        String value = e.getNewValue().toString().trim();
        switch (property) {
            case ConfigData.EmailSender:
                JTF_from.setText(value);
                break;
            case ConfigData.MailHost:
                c_mailHost = value;
                break;
            case ConfigData.CommentAddr:
                c_toComments = value;
                break;
            case ConfigData.BugsAddr:
                c_toBugs = value;
                break;
            case ConfigData.UseDefaultMailClient:
                c_useSmtp = !value.equals("1");
                updateDisplay();
                break;
            case ConfigData.ProjDir:
                c_projectsPath = value;
                break;
            case ConfigData.CurrentProj:
                c_runPath = Util.parse(value);
                break;
            case ConfigData.UseOutlookFlg:
                outlookFlg = "1".equals(value);
                break;
        }

    }

    private void updateDisplay() {
        JL_from.setVisible(c_useSmtp);
        JTF_from.setVisible(c_useSmtp);

        JL_to.setVisible(c_useSmtp);
        JTF_to.setVisible(c_useSmtp);

        JL_subject.setVisible(c_useSmtp);
        JTF_subject.setVisible(c_useSmtp);

        JSP_text.setVisible(c_useSmtp);

        JL_clientNote.setVisible(!c_useSmtp);

        JB_send.setVisible(c_useSmtp);
        JB_client.setVisible(!c_useSmtp);

        Dimension size = JP_main.getPreferredSize();
        size.height += 50;
        setSize(size);

    }

    private static ConfigData c_configData;

    /**
     *
     * @param cd
     */
    public static void listen(ConfigData cd) {
        c_configData = cd;
    }

    /**
     *
     * @param evt
     */
    @Override
    protected void exit_form(java.awt.event.WindowEvent evt) {
        this.dispose();
        if (c_configData != null) {
            c_configData.removePropertyChangeListener(this);
        }
    }
}
