/******************************************************************************
* Copyright 1996-2014 United States Government as represented by the
* Administrator of the National Aeronautics and Space Administration.
* All Rights Reserved.
******************************************************************************/

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.event.*;
import gsfc.nssdc.cdf.*;

/** Output to CDF options dialog for CDFExport
 */

public class ExportToCDFOptions extends JDialog implements CDFConstants {

    static final long serialVersionUID = 1L;

    private JFrame myFrame;
    private static ExportToCDFOptions dialog;
    protected CDFExport cdfexport;

    private ButtonGroup majoritygp;
    private JRadioButton majority0;
    private JRadioButton majority1;
    private JRadioButton majority2;

    private ButtonGroup encodinggp;
    private JRadioButton encoding1;
    private JRadioButton encoding2;

    private ButtonGroup formatgp;
    private JRadioButton format1;
    private JRadioButton format2;

    private ButtonGroup compressiongp;
    private JRadioButton compression1;
    private JRadioButton compression2;
    private JRadioButton compression3;
    private JRadioButton compression4;
    private JRadioButton compression5;

    private ButtonGroup checksumgp;
    private JRadioButton checksum1;
    private JRadioButton checksum2;
    private JRadioButton checksum3;

    private JCheckBox oec;

    private JTextField compressLevel;

    static boolean defaultModal = true;

    private static final String ENTER = "Continue";
    private static final String RESET = "Reset";
    private static final String CANCEL = "Cancel";

    ExportToCDFOptions(JFrame parentFrame, boolean modal) {
        super(parentFrame, modal);
    }

    public static ExportToCDFOptions createToCDFOptions(JFrame parentFrame, 
							CDFExport cdfexport, 
							boolean modal) {
	if (dialog == null) {
	  dialog = new ExportToCDFOptions(parentFrame, modal);
	  dialog.getContentPane().setLayout(new BorderLayout());
	}
	dialog.cdfexport = cdfexport;
	dialog.packUIs();
	return dialog;
    }

/** Reenter this dialog
 */

    public void displayToCDFOptions() {
//	dialog.pack();
        dialog.setVisible(true);
    }

/** Pack all UIs into the dialog  
 */
    private void packUIs() {

	dialog.setTitle("Output To CDF Options");

        // Only way to close is to use the buttons
        dialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
        dialog.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent we) {
            }
        });

        dialog.setSize(450,400);

        Dimension ps = dialog.getSize();
        Dimension ss = Toolkit.getDefaultToolkit().getScreenSize();
        dialog.setLocation(ss.width/2 - ps.width/2,
                           ss.height/2 - ps.height/2);

//	dialog.setLocation(0, 0);
        JPanel mp = (JPanel) dialog.getContentPane();
        mp.setBorder(new EmptyBorder(10,10,10,10));

	buildUIs();

        JPanel generalOptionsPanel = new JPanel(true);

        GridBagLayout gbl = new GridBagLayout();
        GridBagConstraints gbc = new GridBagConstraints();

        generalOptionsPanel.setLayout(gbl);
        gbc.anchor = GridBagConstraints.WEST;
//        gbc.fill = GridBagConstraints.HORIZONTAL;
//        gbc.weightx = 1.0;
//	gbc.weighty = 1.0;
//	gbc.gridheight = 1;

        JLabeledPanel jp1 = new JLabeledPanel("Majority");
        jp1.setLayout(new BoxLayout( jp1, BoxLayout.Y_AXIS ));
        jp1.setAlignmentY(LEFT_ALIGNMENT);

        jp1.add(majority0);
        jp1.add(majority1);
        jp1.add(majority2);

//      gbc.gridwidth = 1;
	gbc.gridx = 0;
	gbc.gridy = 0;
        gbl.setConstraints(jp1, gbc);
        generalOptionsPanel.add(jp1);

        gbc.gridx = 1;
        gbc.gridy = 0;
	Component dummy = Box.createRigidArea(new Dimension(50,1));
        gbl.setConstraints(dummy, gbc);
        generalOptionsPanel.add(dummy);

        JLabeledPanel jp2 = new JLabeledPanel("Encoding");
        jp2.setLayout(new BoxLayout( jp2, BoxLayout.Y_AXIS ));
        jp2.setAlignmentY(LEFT_ALIGNMENT);

        jp2.add(encoding1);
        jp2.add(encoding2);

        gbc.gridx = 2;
        gbc.gridy = 0;
        gbl.setConstraints(jp2, gbc);
        generalOptionsPanel.add(jp2);

        gbc.gridx = 3;
        gbc.gridy = 0;
        gbl.setConstraints(dummy, gbc);
        generalOptionsPanel.add(dummy);

        JLabeledPanel jp3 = new JLabeledPanel("Format");
        jp3.setLayout(new BoxLayout( jp3, BoxLayout.Y_AXIS ));
        jp3.setAlignmentY(LEFT_ALIGNMENT);

        jp3.add(format1);
        jp3.add(format2);

        gbc.gridx = 4;        
        gbc.gridy = 0;        
        gbl.setConstraints(jp3, gbc);
        generalOptionsPanel.add(jp3);

        JLabeledPanel jp4 = new JLabeledPanel("Compression");
        jp4.setLayout(new BoxLayout( jp4, BoxLayout.Y_AXIS ));
        jp4.setAlignmentY(LEFT_ALIGNMENT);
//        jp4.setAlignmentX(LEFT_ALIGNMENT);

        jp4.add(compression1);
        jp4.add(compression2);
        jp4.add(compression3);
        jp4.add(compression4);

	JPanel anew5 = new JPanel(new FlowLayout(), true);
	anew5.add(compression5);
	anew5.add(compressLevel);
	compressLevel.setEnabled(false);
        jp4.add(anew5);

        gbc.gridx = 0;        
        gbc.gridy = 1;        
        gbl.setConstraints(jp4, gbc);
        generalOptionsPanel.add(jp4);

        gbc.gridx = 1;
        gbc.gridy = 1;
        gbl.setConstraints(dummy, gbc);
        generalOptionsPanel.add(dummy);

        JLabeledPanel jp5 = new JLabeledPanel("Checksum");
        jp5.setLayout(new BoxLayout( jp5, BoxLayout.Y_AXIS ));
        jp5.setAlignmentY(LEFT_ALIGNMENT);
//        jp4.setAlignmentX(LEFT_ALIGNMENT);

        jp5.add(checksum1);
        jp5.add(checksum2);
        jp5.add(checksum3);

        gbc.gridx = 2;
        gbc.gridy = 1;
        gbl.setConstraints(jp5, gbc);
        generalOptionsPanel.add(jp5);

        gbc.gridwidth = GridBagConstraints.REMAINDER;
        gbc.gridx = 0;        
        gbc.gridy = 2;        
        gbl.setConstraints(oec, gbc);
        generalOptionsPanel.add(oec);

        gbc.gridx = 0;        
        gbc.gridy = 3;        
        gbc.gridwidth = GridBagConstraints.REMAINDER;
        gbl.setConstraints(dummy, gbc);
        generalOptionsPanel.add(dummy);

        gbc.gridwidth = GridBagConstraints.REMAINDER;
        gbc.gridx = 0;        
        gbc.gridy = 4;        
        gbl.setConstraints(Box.createVerticalStrut(20), gbc);
        generalOptionsPanel.add(Box.createVerticalStrut(20));

        mp.add(generalOptionsPanel, BorderLayout.CENTER);

        createButtonPanel(mp);

    }

/** Build UIs items
 */
    private void buildUIs() {

        oec = new JCheckBox("Overwrite the existing CDF");
        compressLevel = new JTextField(1);

        majoritygp = new ButtonGroup();
        majority0 = new JRadioButton("Source");
        majority1 = new JRadioButton("Row");
        majority2 = new JRadioButton("Column");
        MajorityListener majorityListener = new MajorityListener();
        majority0.setActionCommand("0");
        majority1.setActionCommand("1");
        majority2.setActionCommand("2");
        majority0.addActionListener(majorityListener);
        majority1.addActionListener(majorityListener);
        majority2.addActionListener(majorityListener);
        majority0.setSelected(true);
        majoritygp.add(majority0);
        majoritygp.add(majority1);
        majoritygp.add(majority2);
        majority0.setToolTipText("Use source CDF's majority for the output file");
        majority1.setToolTipText("use Row majority for the output file");
        majority2.setToolTipText("Use Column majority for the output file");

        encodinggp = new ButtonGroup();
        encoding1 = new JRadioButton("Host");
        encoding2 = new JRadioButton("Network");
        EncodingListener encodingListener = new EncodingListener();
        encoding1.setActionCommand("0");
        encoding2.setActionCommand("1");
        encoding1.addActionListener(encodingListener);
        encoding2.addActionListener(encodingListener);
        encoding1.setSelected(true);
        encodinggp.add(encoding1);
        encodinggp.add(encoding2);
        encoding1.setToolTipText("use netork encoding for the output file");
        encoding2.setToolTipText("Use host machine's encoding for the output file");

        formatgp = new ButtonGroup();
        format1 = new JRadioButton("Single-file CDF");
        format2 = new JRadioButton("Multi-file CDF");
        FormatListener formatListener = new FormatListener();
        format1.setActionCommand("1");
        format2.setActionCommand("2");
        format1.addActionListener(formatListener);
        format2.addActionListener(formatListener);
        format1.setSelected(true);
        formatgp.add(format1);
        formatgp.add(format2);
        format1.setToolTipText("Use single file format for the output file");
        format2.setToolTipText("Use multi-file format for the output file");

        compressiongp = new ButtonGroup();
        compression1 = new JRadioButton("None");
        compression2 = new JRadioButton("RLE");
        compression3 = new JRadioButton("Huffman");
        compression4 = new JRadioButton("AHuffman");
        compression5 = new JRadioButton("GZIP");
        CompressionListener compressionListener = new CompressionListener();
        compression1.setActionCommand("0");
        compression2.setActionCommand("1");
        compression3.setActionCommand("2");
        compression4.setActionCommand("3");
        compression5.setActionCommand("5");
        compression1.addActionListener(compressionListener);
        compression2.addActionListener(compressionListener);
        compression3.addActionListener(compressionListener);
        compression4.addActionListener(compressionListener);
        compression5.addActionListener(compressionListener);
        compression1.setSelected(true);
        compressiongp.add(compression1);
        compressiongp.add(compression2);
        compressiongp.add(compression3);
        compressiongp.add(compression4);
        compressiongp.add(compression5);
        compression1.setToolTipText("No compression applied");
        compression2.setToolTipText("Use Run-Length Encoding compression method");
        compression3.setToolTipText("Use Huffman compression method");
        compression4.setToolTipText("Use Adaptive Huffman compression method");
        compression5.setToolTipText("Use GNU GZIP compression method");
        
        checksumgp = new ButtonGroup();
        checksum1 = new JRadioButton("SOURCE");
        checksum2 = new JRadioButton("NO");
        checksum3 = new JRadioButton("MD5");
        ChecksumListener checksumListener = new ChecksumListener();
        checksum1.setActionCommand("0");
        checksum2.setActionCommand("1");
	checksum3.setActionCommand("2");
        checksum1.addActionListener(checksumListener);
        checksum2.addActionListener(checksumListener);
	checksum3.addActionListener(checksumListener);
        checksum1.setSelected(true);
        checksumgp.add(checksum1);
        checksumgp.add(checksum2);
	checksumgp.add(checksum3);
        checksum1.setToolTipText("Use the source checksum method for the exported file");
        checksum2.setToolTipText("Don't use checksum");
	checksum3.setToolTipText("Use MD5 checksum method");

        OptionsListener optionsListener = new OptionsListener();
        oec.addItemListener(optionsListener);
        oec.setToolTipText("Overwrite the existing CDF");
        
        TextFieldListener textFieldListener = new TextFieldListener();
        compressLevel.addActionListener(textFieldListener);
        compressLevel.setToolTipText("Compression level (1-9) for GZIP method");

   }

/** Create selection buttons at the bottom of panel
 */

    private void createButtonPanel(JPanel jp) {

        JButton enterButton = new JButton(ENTER);
        JButton resetButton = new JButton(RESET);
        JButton cancelButton = new JButton(CANCEL);
        JPanel buttonPanel = new JPanel(true);

	SelectionListener selectionListener = new SelectionListener();
        enterButton.addActionListener(selectionListener);
        resetButton.addActionListener(selectionListener);
        cancelButton.addActionListener(selectionListener);

        buttonPanel.add(enterButton);
        buttonPanel.add(Box.createRigidArea(new Dimension(20,1)));
        buttonPanel.add(resetButton);
        buttonPanel.add(Box.createRigidArea(new Dimension(20,1)));
        buttonPanel.add(cancelButton);
	buttonPanel.add(Box.createRigidArea(new Dimension(20,1)));

	enterButton.setToolTipText("Continue to the next step ...");
	resetButton.setToolTipText("Reset the selections to their defaults...");
	cancelButton.setToolTipText("Stop but keep the selections and retrun to the previous step..."); 

        jp.add(buttonPanel, BorderLayout.SOUTH);

    }

/** Reset the selection to the defaults
 */

    public void reset() {

        majority0.setSelected(true);
        encoding1.setSelected(true);
        format1.setSelected(true);
        compression1.setSelected(true);
	compressLevel.setEnabled(false);
	oec.setSelected(false);
	compressLevel.setText("");

	cdfexport.majority = 0;
	cdfexport.encoding = 0;
	cdfexport.format = 1;
	cdfexport.compressionType = 0;
	cdfexport.compressionLevel = 0;
	cdfexport.overwrite = 0;

    }

/** Action for checkboxs selection
 */

    private class OptionsListener implements ItemListener {
      public void itemStateChanged(ItemEvent evt) {
	Object obj = evt.getSource();
	if (obj == oec) { // "Overwrite the Existing CDF" checkbox
	      if (oec.isSelected()) {
                int result =
                  JOptionPane.showConfirmDialog(myFrame,
                                  "Do you want to overwrite the existing "+
                                  "CDF file?",
                                  "Delete Existing File?",
                                  JOptionPane.YES_NO_CANCEL_OPTION);
                if (result == JOptionPane.YES_OPTION)
                   cdfexport.overwrite = 1;
                else {
                   oec.setSelected(false);
		   cdfexport.overwrite = 0;
		}
              } else 
                cdfexport.overwrite = 0;
	}
      }
    }

/** Action for radio buttons for Majority
 */

    private class MajorityListener implements ActionListener {
        public void actionPerformed(ActionEvent e) {
           cdfexport.majority = Integer.parseInt(e.getActionCommand());
        }
    }

/** Action for radio buttons for Encoding
 */

    private class EncodingListener implements ActionListener {
        public void actionPerformed(ActionEvent e) {
           cdfexport.encoding = Integer.parseInt(e.getActionCommand());
        }
    }

/** Action for radio buttons for Format
 */

    private class FormatListener implements ActionListener {
        public void actionPerformed(ActionEvent e) {
           cdfexport.format = Integer.parseInt(e.getActionCommand());
        }
    }

/** Action for radio buttons for Compression
 */

    private class CompressionListener implements ActionListener {
        public void actionPerformed(ActionEvent e) {
           cdfexport.compressionType = Integer.parseInt(e.getActionCommand());
           if (cdfexport.compressionType == 5) { // GZIP- needs a compression level
	     compressLevel.setEnabled(true);	
             String cLevel = compressLevel.getText();
	     if (cLevel.equals(null) || cLevel.trim().length() == 0) {
		compressLevel.setText("5");
             }
           } else {
		compressLevel.setEnabled(false);
	        compressLevel.setText("");
	   }
        }
    }

/** Action for TextField for GZIP compression level
 */

    private class TextFieldListener implements ActionListener {
        public void actionPerformed(ActionEvent e) {
	   String cLevel = ((JTextField)e.getSource()).getText();
           int level = Integer.parseInt(cLevel);
	   if (level < 1 || level > 9) { // bad value
	     Toolkit.getDefaultToolkit().beep();
	     JOptionPane.showMessageDialog(dialog,
                                           "Compression level has to\n"+
                                           "be between 1 and 9",
                                           "Compression Level Error",
					   JOptionPane.ERROR_MESSAGE);
	     compressLevel.setText("");
	   } else { // Set GZIP on
	     compression5.setSelected(true);
	     cdfexport.compressionType = 5; 
	     cdfexport.compressionLevel = level;
	   }
        }
    }

/**
 * Process button events.
 */
    private class SelectionListener implements ActionListener {
	public void actionPerformed(ActionEvent event) {
          Object source = event.getSource();

          if (source instanceof JButton) {
            String action = event.getActionCommand();
            if (action.equals(CANCEL)) {              // Cancel the operation
		dialog.setVisible(false);
		cdfexport.repaint();
            } else if (action.equals(ENTER)) {        // Continue the operation
		if (compression5.isSelected()) { // make sure the compression level
	           String cLevel = compressLevel.getText();
	           if (!cLevel.equals(null) && cLevel.trim().length() != 0) {
		     int compressionlevel = Integer.parseInt(cLevel);
	             if (compressionlevel > 0 && compressionlevel < 10) { // good value
		       dialog.setVisible(false);
		       cdfexport.compressionLevel = compressionlevel;
		     }
		   } else {
	             Toolkit.getDefaultToolkit().beep();
	             JOptionPane.showMessageDialog(dialog,
                                           "Compression level has to\n"+
                                           "be between 1 and 9 for GZIP",
                                           "Compression Level Error",
                                           JOptionPane.ERROR_MESSAGE);
        	     compressLevel.setText("");
		   }
		}
                dialog.setVisible(false);
		cdfexport.repaint();
            } else if (action.equals(RESET)) {        // Reset the selection
		reset();
            }
          }
	}
    }

/**
/** Action for radio buttons for Checksum
 */

    private class ChecksumListener implements ActionListener {
        public void actionPerformed(ActionEvent e) {
	   int value = Integer.parseInt(e.getActionCommand());
	   if (value == 0) 
	     cdfexport.checksum = (long) -1;
	   else if (value == 1)
	     cdfexport.checksum = NONE_CHECKSUM;
	   else if (value == 2)
	     cdfexport.checksum = MD5_CHECKSUM;
        }
    }


}

