/*
 * RowStatisticsDialog.java
 *
 * Created on February 19, 2008, 3:53 PM
 */

package org.statcato.dialogs.stat.basicstats;

import org.statcato.utils.HelperFunctions;
import org.statcato.spreadsheet.*;
import org.statcato.statistics.BasicStatistics;
import org.statcato.*;
import java.util.*;
import javax.swing.*;

/**
 * A dialog for computing statistics for each row in a set of columns 
 * and storing the results in the corresponding rows of a new column.
 * Statistics include sum, mean, standard deviation, minimum, maximum,
 * range, median, sum of squares, N total, N nonmissing, and N missing.
 * 
 * @author  Margaret Yau
 * @version %I%, %G%
 * @see org.statcato.statistics.BasicStatistics
 * @since 1.0
 */
public class RowStatisticsDialog extends StatcatoDialog {

    /** Creates new form RowStatisticsDialog */
    public RowStatisticsDialog(java.awt.Frame parent, boolean modal, Statcato app) {
        super(parent, modal);
        this.ParentSpreadsheet = app.getSpreadsheet();
        this.app = app;
        initComponents();
        
        ButtonGroup group = new ButtonGroup();
        group.add(SumRadioButton);
        group.add(MeanRadioButton);
        group.add(StdevRadioButton);
        group.add(MinRadioButton);
        group.add(MaxRadioButton);
        group.add(RangeRadioButton);
        group.add(MedianRadioButton);
        group.add(SumOfSqRadioButton);
        group.add(NtotalRadioButton);
        group.add(NnonmissingRadioButton);
        group.add(NmissingRadioButton);

        getRootPane().setDefaultButton(OKButton);
        setHelpFile("stat-basic-row");
        name = "Row Statistics";
        description = "For computing a statistic for each row in a set of columns " +
                "and storing the results in the corresponding rows of a new column.";
        helpStrings.add("Enter the names of the input columns. " +
                "Separate column names by spaces (e.g. c2 c4), " +
                "and use a dash to indicate a range of columns (e.g. c10-c15).");
        helpStrings.add("Select the desired statistic.");
        helpStrings.add("Enter the column name (e.g. C1) or variable name " +
                "(e.g. sum) in the Store Results in: text box.");
    }

    /**
     * Updates elements on the dialog so that they have the most
     * current values.  Called by {@link #setVisible} to make
     * sure the dialog displays current values when made visible again.
     * 
     * @see #setVisible(boolean)
     */
    @Override
    public void updateElements() {
    }
    
    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        OKButton = new javax.swing.JButton();
        CancelButton = new javax.swing.JButton();
        jPanel1 = new javax.swing.JPanel();
        jLabel1 = new javax.swing.JLabel();
        InputTextField = new javax.swing.JTextField();
        jLabel8 = new javax.swing.JLabel();
        jPanel2 = new javax.swing.JPanel();
        MeanRadioButton = new javax.swing.JRadioButton();
        NmissingRadioButton = new javax.swing.JRadioButton();
        RangeRadioButton = new javax.swing.JRadioButton();
        MedianRadioButton = new javax.swing.JRadioButton();
        NnonmissingRadioButton = new javax.swing.JRadioButton();
        StdevRadioButton = new javax.swing.JRadioButton();
        NtotalRadioButton = new javax.swing.JRadioButton();
        jLabel2 = new javax.swing.JLabel();
        MinRadioButton = new javax.swing.JRadioButton();
        SumOfSqRadioButton = new javax.swing.JRadioButton();
        SumRadioButton = new javax.swing.JRadioButton();
        MaxRadioButton = new javax.swing.JRadioButton();
        jPanel3 = new javax.swing.JPanel();
        jLabel3 = new javax.swing.JLabel();
        jLabel4 = new javax.swing.JLabel();
        ResultTextField = new javax.swing.JTextField();

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        setTitle("Row Statistics");

        OKButton.setText("OK");
        OKButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                OKButtonActionPerformed(evt);
            }
        });

        CancelButton.setText("Cancel");
        CancelButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                CancelButtonActionPerformed(evt);
            }
        });

        jPanel1.setBorder(javax.swing.BorderFactory.createTitledBorder("Inputs"));

        jLabel1.setText("Input Variables(s):");

        jLabel8.setText("<html>\nEnter valid column names separated by space.<br>\nFor a continuous range of columns,<br>\nseparate using dash (e.g. C1-C30).<br>\n</html>\n");

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                    .addGroup(jPanel1Layout.createSequentialGroup()
                        .addComponent(InputTextField)
                        .addContainerGap())
                    .addComponent(jLabel1)
                    .addComponent(jLabel8, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jLabel1)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(InputTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(18, 18, 18)
                .addComponent(jLabel8)
                .addGap(208, 208, 208))
        );

        jPanel2.setBorder(javax.swing.BorderFactory.createTitledBorder("Statistics"));

        MeanRadioButton.setText("Mean");

        NmissingRadioButton.setText("N missing");

        RangeRadioButton.setText("Range");

        MedianRadioButton.setText("Median");

        NnonmissingRadioButton.setText("N nonmissing");

        StdevRadioButton.setText("Standard Deviation");

        NtotalRadioButton.setText("N total");

        jLabel2.setText("Statistic:");

        MinRadioButton.setText("Minimum");

        SumOfSqRadioButton.setText("Sum of Squares");

        SumRadioButton.setText("Sum");

        MaxRadioButton.setText("Maximum");

        javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
        jPanel2.setLayout(jPanel2Layout);
        jPanel2Layout.setHorizontalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel2Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(SumRadioButton)
                    .addComponent(jLabel2)
                    .addComponent(MeanRadioButton)
                    .addComponent(StdevRadioButton)
                    .addComponent(MinRadioButton)
                    .addComponent(MaxRadioButton)
                    .addComponent(RangeRadioButton))
                .addGap(42, 42, 42)
                .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(SumOfSqRadioButton)
                    .addComponent(MedianRadioButton)
                    .addComponent(NtotalRadioButton)
                    .addComponent(NnonmissingRadioButton)
                    .addComponent(NmissingRadioButton))
                .addContainerGap())
        );
        jPanel2Layout.setVerticalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel2Layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jLabel2)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(SumRadioButton)
                    .addComponent(MedianRadioButton))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(MeanRadioButton)
                    .addComponent(SumOfSqRadioButton))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(StdevRadioButton)
                    .addComponent(NtotalRadioButton))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(MinRadioButton)
                    .addComponent(NnonmissingRadioButton))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(MaxRadioButton)
                    .addComponent(NmissingRadioButton))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(RangeRadioButton)
                .addContainerGap())
        );

        jPanel3.setBorder(javax.swing.BorderFactory.createTitledBorder("Results"));

        jLabel3.setText("Store Results in:");

        jLabel4.setText("(column or variable name)");

        javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3);
        jPanel3.setLayout(jPanel3Layout);
        jPanel3Layout.setHorizontalGroup(
            jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel3Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jLabel3)
                    .addComponent(ResultTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 144, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel4))
                .addContainerGap(79, Short.MAX_VALUE))
        );
        jPanel3Layout.setVerticalGroup(
            jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel3Layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jLabel3)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(ResultTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jLabel4)
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(jPanel3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jPanel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addGroup(layout.createSequentialGroup()
                        .addGap(41, 41, 41)
                        .addComponent(OKButton)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(CancelButton)))
                .addContainerGap())
        );

        layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {CancelButton, OKButton});

        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(jPanel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 50, Short.MAX_VALUE)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(OKButton)
                            .addComponent(CancelButton)))
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, 157, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jPanel3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
                .addContainerGap(19, Short.MAX_VALUE))
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    @SuppressWarnings("unchecked") 
    private void OKButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_OKButtonActionPerformed
        app.compoundEdit = new DialogEdit("row statistics");
        
        // get selected input variables
        int[] columnNumbers = ParentSpreadsheet.getColumnNumbersArrayFromString(InputTextField.getText());       
        
        // check that at least one input variable is selected
        if (columnNumbers.length == 0) {
            app.showErrorDialog("Select at least one input variable.");
            return;
        }
        // check that column/variable for storing results is valid
        String StoreColumn = ResultTextField.getText();
        int storeColumnNum = -1;
        if (!StoreColumn.equals("")) {
            storeColumnNum = ParentSpreadsheet.getColumnNumber(StoreColumn);
            if (storeColumnNum == -1) { // invalid column 
                app.showErrorDialog("Enter a valid column name (e.g. C1) or a valid variable name to store the results.");
                return;
            }
        }        
        else {
            app.showErrorDialog("Enter a column name or variable name to which the results will be stored.");
            return;
        }
            
        String text = "";
        
        Vector<String> ResultVector = new Vector<String>(0);
        Vector<Vector<Cell>> Rows = ParentSpreadsheet.getRowsWithDataAtGivenColumns(columnNumbers);

        for (Enumeration e = Rows.elements(); e.hasMoreElements();) {
            Vector<Cell> Row = (Vector<Cell>) e.nextElement();
            if (Row.size() == 0) { // empty row
                ResultVector.addElement("");
            }
            else {
                Object[] conversions = HelperFunctions.ConvertInputVectorToNumbers2(Row);
                Vector<Double> RowVector = (Vector<Double>) conversions[0];
                int missing = ((Integer)conversions[1]).intValue();
                int nonmissing = ((Integer)conversions[2]).intValue();
                int total = missing + nonmissing;

                if (conversions == null) {
                    app.showErrorDialog("Invalid input column: all data must be numbers.");
                    return;
                }

                if (SumRadioButton.isSelected()) {
                    double sum = BasicStatistics.sum(RowVector);                    
                    ResultVector.addElement(sum + "");   
                }
                else if (MeanRadioButton.isSelected()) {
                    Double mean = BasicStatistics.mean(RowVector);
                    if (mean == null)
                        ResultVector.addElement("*");
                    else
                        ResultVector.addElement(mean.doubleValue() + "");   
                }
                else if (StdevRadioButton.isSelected()) {
                    Double stdev = BasicStatistics.stdev(RowVector);
                    if (stdev == null)
                        ResultVector.addElement("*");
                    else
                        ResultVector.addElement(stdev.doubleValue() + "");        
                }
                else if (MaxRadioButton.isSelected()) {
                    Double max = BasicStatistics.max(RowVector);
                    if (max == null)
                        ResultVector.addElement("*");
                    else
                        ResultVector.addElement(max.doubleValue() + "");      
                }
                else if (MinRadioButton.isSelected()) {
                    Double min = BasicStatistics.min(RowVector);
                    if (min == null)
                        ResultVector.addElement("*");          
                    else
                        ResultVector.addElement(min.doubleValue() + "");     
                }
                else if (RangeRadioButton.isSelected()) {
                    Double range = BasicStatistics.range(RowVector);
                    if (range == null)
                        ResultVector.addElement("*");
                    else
                        ResultVector.addElement(range.doubleValue() + "");  
                }
                else if (MedianRadioButton.isSelected()) {
                    Double median = BasicStatistics.median(RowVector);
                    if (median == null)
                       ResultVector.addElement("*");
                    else
                        ResultVector.addElement(median.doubleValue() + "");     
                }
                else if (SumOfSqRadioButton.isSelected()) {
                    double sum = BasicStatistics.sumOfSquares(RowVector);
                    ResultVector.addElement(sum + "");    
                }
                else if (NtotalRadioButton.isSelected()) {
                    ResultVector.addElement(total + "");
                }
                else if (NnonmissingRadioButton.isSelected()) {
                    ResultVector.addElement(nonmissing + "");
                }
                else if (NmissingRadioButton.isSelected()) {
                    ResultVector.addElement(missing + "");
                }
            }
        }
        
        if (SumRadioButton.isSelected()) {
            text += "sum of " + InputTextField.getText();
        }
        else if (MeanRadioButton.isSelected()) {
            text += "mean of " + InputTextField.getText();
        }
        else if (StdevRadioButton.isSelected()) {
            text += "standard deviation of " + InputTextField.getText();
        }
        else if (MaxRadioButton.isSelected()) {
            text += "max of " + InputTextField.getText();
        }
        else if (MinRadioButton.isSelected()) {
            text += "min of " + InputTextField.getText();
        }
        else if (RangeRadioButton.isSelected()) {
            text += "range of " + InputTextField.getText();
        }
        else if (MedianRadioButton.isSelected()) {
            text += "median of " + InputTextField.getText();
        }
        else if (SumOfSqRadioButton.isSelected()) {
            text += "sum of squares of " + InputTextField.getText();
        }
        else if (NtotalRadioButton.isSelected()) {
            text += "N total of " + InputTextField.getText();
        }
        else if (NnonmissingRadioButton.isSelected()) {
            text += "N nonmissing of " + InputTextField.getText();
        }
        else if (NmissingRadioButton.isSelected()) {
            text += "N missing of " + InputTextField.getText();
        }
        ParentSpreadsheet.setColumn(storeColumnNum, ResultVector);
        text += "<br>Store results in " + StoreColumn;
        
        app.addLogParagraph("Row Statistics", text);

        app.compoundEdit.end();
        app.addCompoundEdit(app.compoundEdit);
        
        setVisible(false);
    }//GEN-LAST:event_OKButtonActionPerformed

    private void CancelButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_CancelButtonActionPerformed
        // close dialog
        setVisible(false);
    }//GEN-LAST:event_CancelButtonActionPerformed
    
    
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton CancelButton;
    private javax.swing.JTextField InputTextField;
    private javax.swing.JRadioButton MaxRadioButton;
    private javax.swing.JRadioButton MeanRadioButton;
    private javax.swing.JRadioButton MedianRadioButton;
    private javax.swing.JRadioButton MinRadioButton;
    private javax.swing.JRadioButton NmissingRadioButton;
    private javax.swing.JRadioButton NnonmissingRadioButton;
    private javax.swing.JRadioButton NtotalRadioButton;
    private javax.swing.JButton OKButton;
    private javax.swing.JRadioButton RangeRadioButton;
    private javax.swing.JTextField ResultTextField;
    private javax.swing.JRadioButton StdevRadioButton;
    private javax.swing.JRadioButton SumOfSqRadioButton;
    private javax.swing.JRadioButton SumRadioButton;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JLabel jLabel8;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JPanel jPanel3;
    // End of variables declaration//GEN-END:variables
    
}
