/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

package org.libreoffice.example.java_scripts;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
import java.util.Vector;
import com.sun.star.script.framework.runtime.XScriptContext;


public class PostNewsgroup extends JFrame {

    // Post to newsgroup objects
    private NewsGroup[] subscribedNewsgroups = null;
    private XScriptContext xscriptcontext = null;

    private final int FRAMEX = 300;
    private final int FRAMEY = 300;
    private final int TEXTBOXWIDTH = 300;
    private final int TEXTBOXHEIGHT = 24;
    private final int TEXTAREAHEIGHT = 70;
    private final int BUTTONWIDTH = 80;
    private final int BUTTONHEIGHT = 30;

    private PostNewsgroup window = null;
    private JComboBox newsgroupComboBox = null;
    private JTextField hostTextField = null;
    private JTextField replyTextField = null;
    private JTextField subjectTextField = null;
    private JTextArea commentTextArea = null;
    private JRadioButton officeHtmlButton = null;
    private JRadioButton officeButton = null;
    private JRadioButton htmlButton = null;
    private JButton postButton = null;
    private JButton cancelButton = null;

    // JFrame for launch progress dialog
    private StatusWindow statusWindow = null;
    private String statusLine = "";

    // Tool tip text
    private final String newsgroupText = "Newsgroup name";
    private final String hostText = "Newsgroup host/server name";
    private final String replyText = "Email address to reply to";
    private final String subjectText = "Subject title for the mail";
    private final String commentText = "Additional comment on mail";
    private final String officeHtmlText =
        "Post as both Office and HTML attachments";
    private final String officeText = "Post as Office attachment only";
    private final String htmlText = "Post as HTML attachment only";
    private final String postText = "Post to newsgroup";
    private final String cancelText = "Cancel post to newsgroup";


    public void post(XScriptContext xsc) {
        xscriptcontext = xsc;
        window = this;

        // create mailcap and mimetypes files (fix for classloader problem)
        MimeConfiguration.createFiles(xscriptcontext);

        this.setTitle("Post Document To Newsgroup");
        this.setLocation(FRAMEX, FRAMEY);

        this.addFocusListener(new FocusAdapter() {
            public void focusGained(FocusEvent event) {
                System.out.println("Focus gained");
                window.update(window.getGraphics());
            }

            public void focusLost(FocusEvent event) {
                System.out.println("Focus lost");
            }
        });

        Container container = getContentPane();
        container.setLayout(new GridBagLayout());
        GridBagConstraints constraints = new GridBagConstraints();
        constraints.fill = GridBagConstraints.BOTH;

        JPanel labelPanel = constructLabelPanel();
        JPanel textPanel = constructTextPanel();
        JPanel optionPanel = constructOptionPanel();
        JPanel buttonPanel = constructButtonPanel();

        constraints.gridx = 0;
        constraints.gridy = 0;
        constraints.gridwidth = 1;
        constraints.gridheight = 3;
        constraints.insets = new Insets(15, 15, 5, 5);
        container.add(labelPanel, constraints);

        constraints.gridx = 1;
        constraints.gridy = 0;
        constraints.gridwidth = 4;
        constraints.gridheight = 3;
        constraints.insets = new Insets(15, 5, 5, 15);
        container.add(textPanel, constraints);

        constraints.gridx = 0;
        constraints.gridy = 3;
        constraints.gridwidth = 5;
        constraints.gridheight = 1;
        constraints.insets = new Insets(5, 15, 5, 15);
        container.add(optionPanel, constraints);

        constraints.gridx = 0;
        constraints.gridy = 4;
        constraints.gridwidth = 5;
        constraints.gridheight = 1;
        constraints.insets = new Insets(5, 5, 5, 5);
        container.add(buttonPanel, constraints);

        this.pack();
        this.setResizable(false);
        this.setVisible(true);
    }


    private JPanel constructLabelPanel() {
        JLabel newsgroupLabel = new JLabel("Newsgroup:");
        JLabel hostLabel = new JLabel("Host:");
        JLabel replyLabel = new JLabel("Reply:");
        JLabel subjectLabel = new JLabel("Subject:");
        JLabel commentLabel = new JLabel("Comment:");

        newsgroupLabel.setToolTipText(newsgroupText);
        hostLabel.setToolTipText(hostText);
        replyLabel.setToolTipText(replyText);
        subjectLabel.setToolTipText(subjectText);
        commentLabel.setToolTipText(commentText);

        JPanel newsgroupPanel = new JPanel();
        newsgroupPanel.setLayout(new BorderLayout());
        newsgroupPanel.add(newsgroupLabel, "West");
        JPanel hostPanel = new JPanel();
        hostPanel.setLayout(new BorderLayout());
        hostPanel.add(hostLabel, "West");
        JPanel replyPanel = new JPanel();
        replyPanel.setLayout(new BorderLayout());
        replyPanel.add(replyLabel, "West");
        JPanel subjectPanel = new JPanel();
        subjectPanel.setLayout(new BorderLayout());
        subjectPanel.add(subjectLabel, "West");
        JPanel commentPanel = new JPanel();
        commentPanel.setLayout(new BorderLayout());
        commentPanel.add(commentLabel, "West");
        JPanel emptyPanel = new JPanel();

        final int labelWidth = 80;
        newsgroupPanel.setPreferredSize(new Dimension(labelWidth, TEXTBOXHEIGHT));
        hostPanel.setPreferredSize(new Dimension(labelWidth, TEXTBOXHEIGHT));
        replyPanel.setPreferredSize(new Dimension(labelWidth, TEXTBOXHEIGHT));
        subjectPanel.setPreferredSize(new Dimension(labelWidth, TEXTBOXHEIGHT));
        commentPanel.setPreferredSize(new Dimension(labelWidth, TEXTBOXHEIGHT));

        JPanel panel = new JPanel();
        panel.setLayout(new GridBagLayout());
        GridBagConstraints constraints = new GridBagConstraints();
        constraints.fill = GridBagConstraints.BOTH;
        constraints.insets = new Insets(5, 5, 5, 5);

        constraints.gridx = 0;
        constraints.gridy = 0;
        constraints.gridwidth = 1;
        constraints.gridheight = 1;
        constraints.weightx = constraints.weighty = 0.0;
        panel.add(newsgroupPanel, constraints);

        constraints.gridx = 0;
        constraints.gridy = 1;
        constraints.gridwidth = 1;
        constraints.gridheight = 1;
        panel.add(hostPanel, constraints);

        constraints.gridx = 0;
        constraints.gridy = 2;
        constraints.gridwidth = 1;
        constraints.gridheight = 1;
        panel.add(replyPanel, constraints);

        constraints.gridx = 0;
        constraints.gridy = 3;
        constraints.gridwidth = 1;
        constraints.gridheight = 1;
        panel.add(subjectPanel, constraints);

        constraints.gridx = 0;
        constraints.gridy = 4;
        constraints.gridwidth = 1;
        constraints.gridheight = 1;
        panel.add(commentPanel, constraints);

        constraints.gridx = 0;
        constraints.gridy = 5;
        constraints.gridwidth = 1;
        constraints.gridheight = 1;
        constraints.weightx = constraints.weighty = 1.0;
        panel.add(emptyPanel, constraints);

        return panel;
    }


    private JPanel constructTextPanel() {
        hostTextField = new JTextField();
        hostTextField.setPreferredSize(new Dimension(TEXTBOXWIDTH, TEXTBOXHEIGHT));
        hostTextField.setToolTipText(hostText);
        hostTextField.setBorder(new EtchedBorder());

        //optionPanel.setBorder( new TitledBorder( new EtchedBorder(), "Document Format" ) );
        newsgroupComboBox = getNewsgroupCombo();

        replyTextField = new JTextField();
        replyTextField.setPreferredSize(new Dimension(TEXTBOXWIDTH, TEXTBOXHEIGHT));
        replyTextField.setToolTipText(replyText);
        replyTextField.setBorder(new EtchedBorder());

        subjectTextField = new JTextField();
        subjectTextField.setPreferredSize(new Dimension(TEXTBOXWIDTH, TEXTBOXHEIGHT));
        subjectTextField.setToolTipText(subjectText);
        subjectTextField.setBorder(new EtchedBorder());

        commentTextArea = new JTextArea();
        commentTextArea.setPreferredSize(new Dimension(TEXTBOXWIDTH, TEXTAREAHEIGHT));
        commentTextArea.setToolTipText(commentText);
        commentTextArea.setBorder(new EtchedBorder());

        JPanel panel = new JPanel();
        panel.setLayout(new GridBagLayout());
        GridBagConstraints constraints = new GridBagConstraints();
        constraints.fill = GridBagConstraints.BOTH;
        constraints.insets = new Insets(5, 5, 5, 5);

        constraints.gridx = 0;
        constraints.gridy = 0;
        constraints.gridwidth = 1;
        constraints.gridheight = 1;
        panel.add(newsgroupComboBox, constraints);

        constraints.gridx = 0;
        constraints.gridy = 1;
        constraints.gridwidth = 1;
        constraints.gridheight = 1;
        panel.add(hostTextField, constraints);

        constraints.gridx = 0;
        constraints.gridy = 2;
        constraints.gridwidth = 1;
        constraints.gridheight = 1;
        panel.add(replyTextField, constraints);

        constraints.gridx = 0;
        constraints.gridy = 3;
        constraints.gridwidth = 1;
        constraints.gridheight = 1;
        panel.add(subjectTextField, constraints);

        constraints.gridx = 0;
        constraints.gridy = 4;
        constraints.gridwidth = 1;
        constraints.gridheight = 2;
        panel.add(commentTextArea, constraints);

        return panel;
    }


    private JComboBox getNewsgroupCombo() {
        newsgroupComboBox = new JComboBox();
        //newsgroupComboBox.setBorder( new EtchedBorder() );

        newsgroupComboBox.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                // when newsgroup is selected
                if (subscribedNewsgroups != null) {
                    int position = newsgroupComboBox.getSelectedIndex();

                    if (position != -1) {
                        hostTextField.setText(subscribedNewsgroups[ position ].getHostName());
                        newsgroupComboBox.setToolTipText("Newsgroup name: " +
                                                         subscribedNewsgroups[ position ].getNewsgroupName() + "  (Host name: " +
                                                         subscribedNewsgroups[ position ].getHostName() + ")");
                    }
                }
            }
        });

        NewsGroup groupToSend = null;
        SubscribedNewsgroups newsgroups = new SubscribedNewsgroups();
        subscribedNewsgroups = newsgroups.getNewsGroups();

        // Test for no .mozilla or no subscribed newsgroups
        // subscribedNewsgroups = null;

        if (subscribedNewsgroups == null) {
            JOptionPane.showMessageDialog(window,
                                          "No subscribed newsgroups found in mozilla/netscape profile \nPlease enter newsgroup and host name",
                                          "Newsgroups Information", JOptionPane.INFORMATION_MESSAGE);
        } else {
            // Copy all newsgroups into a vector for comparison
            // Alter entries (to include host name) if duplication is found
            ArrayList vector = new ArrayList(subscribedNewsgroups.length);

            for (int i = 0; i < subscribedNewsgroups.length; i++) {
                vector.add(subscribedNewsgroups[i].getNewsgroupName());
            }

            // Compare and alter
            for (int i = 0; i < subscribedNewsgroups.length; i++) {
                // check if combo box already has a newsgroup with same name
                // then add host name to differentiate
                for (int j = 0; j < subscribedNewsgroups.length; j++) {
                    if (j != i
                        && subscribedNewsgroups[j].getNewsgroupName().equalsIgnoreCase(
                            subscribedNewsgroups[i].getNewsgroupName())) {
                        vector.set(j, subscribedNewsgroups[j].getNewsgroupName() + "  (" +
                                   subscribedNewsgroups[j].getHostName() + ")");
                        vector.set(i, subscribedNewsgroups[i].getNewsgroupName() + "  (" +
                                   subscribedNewsgroups[i].getHostName() + ")");
                    }
                }
            }

            // Copy converted newsgroups from vector to combo box
            for (int i = 0; i < subscribedNewsgroups.length; i++) {
                newsgroupComboBox.addItem(vector.elementAt(i));
            }
        }// else

        newsgroupComboBox.setPreferredSize(new Dimension(TEXTBOXWIDTH, TEXTBOXHEIGHT));
        newsgroupComboBox.setEditable(true);

        return newsgroupComboBox;
    }



    private JPanel constructOptionPanel() {
        officeHtmlButton = new JRadioButton("Office and HTML", true);
        officeHtmlButton.setToolTipText(officeHtmlText);

        officeButton = new JRadioButton("Office");
        officeButton.setToolTipText(officeText);

        htmlButton = new JRadioButton("HTML");
        htmlButton.setToolTipText(htmlText);

        JRadioButton[] rbuttons = { officeHtmlButton, officeButton, htmlButton };
        ButtonGroup radioButtonGroup = new ButtonGroup();

        for (int i = 0; i < rbuttons.length; i++) {
            radioButtonGroup.add(rbuttons[i]);
        }

        JPanel optionPanel = new JPanel();
        optionPanel.setBorder(new TitledBorder(new EtchedBorder(), "Document Format"));
        optionPanel.setLayout(new GridBagLayout());
        GridBagConstraints constraints = new GridBagConstraints();
        constraints.fill = GridBagConstraints.BOTH;

        constraints.gridx = 0;
        constraints.gridy = 0;
        constraints.gridwidth = 1;
        constraints.gridheight = 1;
        constraints.insets = new Insets(5, 5, 5, 30);
        optionPanel.add(officeHtmlButton, constraints);

        constraints.gridx = 1;
        constraints.gridy = 0;
        constraints.gridwidth = 1;
        constraints.gridheight = 1;
        constraints.insets = new Insets(5, 20, 5, 30);
        optionPanel.add(officeButton, constraints);

        constraints.gridx = 2;
        constraints.gridy = 0;
        constraints.gridwidth = 1;
        constraints.gridheight = 1;
        constraints.insets = new Insets(5, 20, 5, 5);
        optionPanel.add(htmlButton, constraints);

        return optionPanel;
    }



    public boolean sendingActions() {
        // posting actions
        // Validate the data
        if (isValidData()) {
            // Create status window
            StatusWindow statusWindow = new StatusWindow(window,  "Posting to Newsgroup",
                    FRAMEX, FRAMEY);

            statusWindow.setVisible(true);
            statusLine = "Ready to send...";
            statusWindow.setStatus(0, statusLine);

            // Get the boolean values for HTML/Office document
            // params: ( XScriptContext, StatusWindow, html document, office document )

            boolean html = false;
            boolean office = false;

            if (officeHtmlButton.isSelected()) {
                html = true;
                office = true;
            }

            if (officeButton.isSelected()) {
                office = true;
                html = false;
            }

            if (htmlButton.isSelected()) {
                html = true;
                office = false;
            }

            OfficeAttachment officeAttach = new OfficeAttachment(xscriptcontext,
                    statusWindow, html, office);

            statusLine = "Getting user input";
            statusWindow.setStatus(2, statusLine);
            // Get replyto, subject, comment from textboxes
            String replyto = replyTextField.getText();
            String subject = subjectTextField.getText();
            String comment = commentTextArea.getText();

            // Get newsgroup from combo box (corresponding position)
            String host = "";
            String group = "";
            int position = newsgroupComboBox.getSelectedIndex();

            if (subscribedNewsgroups == null || position == -1) {
                host = hostTextField.getText();
                group = newsgroupComboBox.getSelectedItem().toString();
            } else {
                host = subscribedNewsgroups[ position ].getHostName();
                group = subscribedNewsgroups[ position ].getNewsgroupName();
            }

            statusLine = "Creating sender object";
            statusWindow.setStatus(3, statusLine);
            Sender sender = new Sender(statusWindow, officeAttach, replyto, subject,
                                       comment, host, group);

            if (!sender.sendMail()) {
                statusWindow.enableCancelButton(true);
                officeAttach.cleanUpOnError();
                return false;
            }

            statusLine = "Send is complete";
            statusWindow.setStatus(14, statusLine);
        } else {
            return false;
        }

        return true;
    }


    private JPanel constructButtonPanel() {
        Action postAction = new AbstractAction() {
            public void actionPerformed(ActionEvent event) {
                // posting actions
                sendingActions();
            }// actionPerformed
        };

        Action cancelAction = new AbstractAction() {
            public void actionPerformed(ActionEvent event) {
                // cancelling actions
                window.dispose();
            }
        };

        postButton = new JButton();
        postButton.setAction(postAction);
        postButton.setToolTipText(postText);
        postButton.setText("Post");
        postButton.setPreferredSize(new Dimension(BUTTONWIDTH + 20, BUTTONHEIGHT));

        cancelButton = new JButton();
        cancelButton.setAction(cancelAction);
        cancelButton.setToolTipText(cancelText);
        cancelButton.setText("Cancel");
        cancelButton.setPreferredSize(new Dimension(BUTTONWIDTH + 20, BUTTONHEIGHT));

        JSeparator sep = new JSeparator(SwingConstants.HORIZONTAL);

        JPanel buttonPanel = new JPanel();
        buttonPanel.setLayout(new GridBagLayout());
        GridBagConstraints constraints = new GridBagConstraints();
        constraints.fill = GridBagConstraints.BOTH;
        constraints.insets = new Insets(5, 5, 5, 5);

        JPanel emptyPanel1 = new JPanel();
        emptyPanel1.setPreferredSize(new Dimension(BUTTONWIDTH, BUTTONHEIGHT));

        JPanel emptyPanel2 = new JPanel();
        emptyPanel2.setPreferredSize(new Dimension(BUTTONWIDTH, BUTTONHEIGHT));

        constraints.gridx = 0;
        constraints.gridy = 0;
        constraints.gridwidth = 4;
        constraints.gridheight = 1;
        buttonPanel.add(sep, constraints);

        constraints.gridx = 0;
        constraints.gridy = 1;
        constraints.gridwidth = 1;
        constraints.gridheight = 1;
        buttonPanel.add(emptyPanel1, constraints);

        constraints.gridx = 1;
        constraints.gridy = 1;
        constraints.gridwidth = 1;
        constraints.gridheight = 1;
        buttonPanel.add(emptyPanel2, constraints);

        constraints.gridx = 2;
        constraints.gridy = 1;
        constraints.gridwidth = 1;
        constraints.gridheight = 1;
        buttonPanel.add(postButton, constraints);

        constraints.gridx = 3;
        constraints.gridy = 1;
        constraints.gridwidth = 1;
        constraints.gridheight = 1;
        constraints.insets = new Insets(5, 5, 5, 0);
        buttonPanel.add(cancelButton, constraints);

        return buttonPanel;
    }


    public void enableButtons(boolean enable) {
        if (enable) {
            postButton.setEnabled(true);
            cancelButton.setEnabled(true);
        } else {
            postButton.setEnabled(false);
            cancelButton.setEnabled(false);
        }
    }


    private boolean isValidData() {
        // newsgroupComboBox must not be blank (format? dots and whitespace)
        String newsgroupString = "";
        int position = newsgroupComboBox.getSelectedIndex();

        if (subscribedNewsgroups == null || position == -1) {
            newsgroupString = newsgroupComboBox.getSelectedItem().toString();
        } else {
            newsgroupString = subscribedNewsgroups[ position ].getNewsgroupName();
        }

        if (newsgroupString.length() == 0) {
            newsgroupComboBox.requestFocus();
            JOptionPane.showMessageDialog(window, "Please enter a newsgroup name",
                                          "Input Error", JOptionPane.ERROR_MESSAGE);
            return false;
        }


        // hostTextField must not be blank (format?)
        String  hostString = hostTextField.getText();

        if (hostString.length() == 0) {
            hostTextField.requestFocus();
            JOptionPane.showMessageDialog(window, "Please enter a hostname", "Input Error",
                                          JOptionPane.ERROR_MESSAGE);
            return false;
        }


        // replyTextField must have <string>@<string>.<string>
        // (string at least 2 chars long)
        // consider <s>.<s>@<s>.<s>.<s> format? (array of dot positions?)
        String replyString = replyTextField.getText();
        int atPos = replyString.indexOf("@");
        int dotPos = replyString.lastIndexOf(".");
        int length = replyString.length();

        if (length == 0 || atPos == -1 || dotPos == -1 || atPos < 2 || dotPos < atPos
            || dotPos + 2 == length || atPos + 2 == dotPos
            || atPos != replyString.lastIndexOf("@") || replyString.indexOf(" ") != -1) {
            replyTextField.requestFocus();
            JOptionPane.showMessageDialog(window,
                                          "Please enter a valid reply to email address", "Input Error",
                                          JOptionPane.ERROR_MESSAGE);
            return false;
        }


        // subjectTextField must not be blank?
        String subjectString = subjectTextField.getText();

        if (subjectString.length() == 0) {
            subjectTextField.requestFocus();
            JOptionPane.showMessageDialog(window, "Please enter subject title",
                                          "Input Error", JOptionPane.ERROR_MESSAGE);
            return false;
        }

        // details are valid
        return true;
    }

}
