/*
 * -------------------------------------------------------------------------
 *      $Id: RandomGen.java,v 1.8 2004/05/26 18:27:38 estewart Exp $
 * -------------------------------------------------------------------------
 *      Copyright (c) 1999 Visual Numerics Inc. All Rights Reserved.
 *
 *      This software is confidential information which is proprietary to
 *      and a trade secret of Visual Numerics, Inc.  Use, duplication or
 *      disclosure is subject to the terms of an appropriate license
 *      agreement.
 *
 *      VISUAL NUMERICS MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE
 *      SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING
 *      BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY,
 *      FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. VISUAL
 *      NUMERICS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
 *      AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR
 *      ITS DERIVATIVES.
 *--------------------------------------------------------------------------
 */

package com.imsl.demo.RandomGen;
import java.awt.*;
import com.imsl.chart.*;
import com.imsl.stat.Random;
import com.imsl.math.Cholesky;
import com.imsl.demo.gallery.Describe;


/**
 *
 * @author  Masayuki Saito
 * @created October 21, 2002
 */
public class RandomGen extends javax.swing.JFrame {

    private javax.swing.JDialog displayFrame;
    private JPanelChart displayArea;
    private Bar bar;
    private int randomK = 0;
    private int numPoints = 1000;
    private int numBins = 20;
    private final int numDist = 21;
    private javax.swing.JRadioButton rb[] = new javax.swing.JRadioButton[numDist];
    private String[] rname = new String[numDist];
    private boolean textUpdateFlag;
    
    
    /** Creates new form RandomGen */
    public RandomGen(boolean exitOnClose) {
        if (!exitOnClose) {
            // remove the WindowListener, installed by JFrame, that
            // exits the application when the window is closed.
            Object l[] = getListeners(java.awt.event.WindowListener.class);
            for (int k = 0;  k < l.length;  k++) {
                removeWindowListener((java.awt.event.WindowListener)l[k]);
            }
        }
        
        initComponents();
        jMenuItem1.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_P, (java.awt.event.ActionEvent.CTRL_MASK)));
        Describe des = new Describe(this, "/com/imsl/demo/RandomGen/RandomGen.html");
        des.show();
        Dimension ds = des.getSize();
        
        Dimension ss = getToolkit().getScreenSize();
        setResizable(false);
        setLocation(ss.width-ds.width, ds.height);
        Dimension ts = getSize();
        
        int w = Math.min(ss.width/2, ss.height-ds.height-32);
        w = Math.min(w, ss.width-ts.width-ss.width/4);
        displayArea = new JPanelChart();
        displayArea.setPreferredSize(new java.awt.Dimension(w, w));
        displayArea.setChart(new Chart());
        displayFrame = new javax.swing.JDialog();
        displayFrame.setTitle("Distribution");
        displayFrame.setLocation(ss.width-ds.width+ts.width, ds.height);
        displayFrame.getContentPane().add(displayArea, java.awt.BorderLayout.CENTER);
        displayFrame.pack();
        displayFrame.show();
        rb[randomK].setSelected(true);
        //methodActionPerformed(String.valueOf(numPoints));
        updateChart();
    }
    
    /** 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.
     */
    private void initComponents() {//GEN-BEGIN:initComponents
        jPanel1 = new javax.swing.JPanel();
        jPanel2 = new javax.swing.JPanel();
        jLabel1 = new javax.swing.JLabel();
        jTextField1 = new javax.swing.JTextField();
        jLabel2 = new javax.swing.JLabel();
        jTextField2 = new javax.swing.JTextField();
        jPanel3 = new javax.swing.JPanel();
        set_rname();
        for (int i=0; i<numDist ;i++){
            rb[i] = new javax.swing.JRadioButton(rname[i]);
            jPanel3.add(rb[i]);
            rb[i].addActionListener(new java.awt.event.ActionListener() {
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    String eventname = new String(evt.getActionCommand());
                    methodActionPerformed(eventname);
                }
            });
        }
        jPanel4 = new javax.swing.JPanel();
        jTextArea1 = new javax.swing.JTextArea();
        jMenuBar1 = new javax.swing.JMenuBar();
        jMenu1 = new javax.swing.JMenu();
        jMenuItem1 = new javax.swing.JMenuItem();
        jSeparator = new javax.swing.JSeparator();
        jMenuItem2 = new javax.swing.JMenuItem();
        jMenu2 = new javax.swing.JMenu();
        jMenuItem3 = new javax.swing.JMenuItem();

        getContentPane().setLayout(new java.awt.GridLayout(1, 1));

        setTitle("Random Number Distributions        ");
        addWindowListener(new java.awt.event.WindowAdapter() {
            public void windowClosing(java.awt.event.WindowEvent evt) {
                exitForm(evt);
            }
        });

        jPanel1.setLayout(new java.awt.BorderLayout());

        jPanel1.setMaximumSize(new java.awt.Dimension(300, 400));
        jPanel1.setPreferredSize(new java.awt.Dimension(300, 400));
        jPanel2.setLayout(new java.awt.GridLayout(2, 2));

        jPanel2.setMaximumSize(new java.awt.Dimension(400, 40));
        jPanel2.setMinimumSize(new java.awt.Dimension(0, 0));
        jPanel2.setPreferredSize(new java.awt.Dimension(300, 40));
        jLabel1.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
        jLabel1.setText("Number of Samples: ");
        jLabel1.setMaximumSize(new java.awt.Dimension(100, 20));
        jLabel1.setMinimumSize(new java.awt.Dimension(25, 10));
        jLabel1.setPreferredSize(new java.awt.Dimension(100, 20));
        jPanel2.add(jLabel1);

        jTextField1.setText(String.valueOf(numPoints));
        jTextField1.setMaximumSize(new java.awt.Dimension(50, 20));
        jTextField1.setMinimumSize(new java.awt.Dimension(0, 0));
        jTextField1.setPreferredSize(new java.awt.Dimension(50, 20));
        jTextField1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jTextField1ActionPerformed(evt);
            }
        });

        jPanel2.add(jTextField1);

        jLabel2.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
        jLabel2.setText("Number of bins: ");
        jLabel2.setMaximumSize(new java.awt.Dimension(100, 20));
        jLabel2.setPreferredSize(new java.awt.Dimension(100, 20));
        jPanel2.add(jLabel2);

        jTextField2.setText(String.valueOf(numBins));
        jTextField2.setMaximumSize(new java.awt.Dimension(50, 20));
        jTextField2.setPreferredSize(new java.awt.Dimension(50, 20));
        jTextField2.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jTextField2ActionPerformed(evt);
            }
        });

        jPanel2.add(jTextField2);

        jPanel1.add(jPanel2, java.awt.BorderLayout.NORTH);

        jPanel3.setLayout(new java.awt.GridLayout(11, 2));

        jPanel3.setMaximumSize(new java.awt.Dimension(400, 250));
        jPanel3.setPreferredSize(new java.awt.Dimension(300, 400));
        jPanel1.add(jPanel3, java.awt.BorderLayout.CENTER);

        jPanel4.setLayout(new java.awt.GridLayout(1, 0));

        jPanel4.setMaximumSize(new java.awt.Dimension(400, 100));
        jPanel4.setPreferredSize(new java.awt.Dimension(300, 100));
        jTextArea1.setEditable(false);
        jTextArea1.setMaximumSize(new java.awt.Dimension(300, 100));
        jTextArea1.setMinimumSize(new java.awt.Dimension(0, 0));
        jTextArea1.setPreferredSize(new java.awt.Dimension(300, 100));
        jPanel4.add(jTextArea1);

        jPanel1.add(jPanel4, java.awt.BorderLayout.SOUTH);

        getContentPane().add(jPanel1);

        jMenu1.setMnemonic('F');
        jMenu1.setText("File");
        jMenuItem1.setMnemonic('P');
        jMenuItem1.setText("Print...");
        jMenuItem1.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/imsl/demo/RandomGen/Print16.gif")));
        jMenuItem1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItem1ActionPerformed(evt);
            }
        });

        jMenu1.add(jMenuItem1);

        jMenu1.add(jSeparator);

        jMenuItem2.setMnemonic('x');
        jMenuItem2.setText("Exit");
        jMenuItem2.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItem2ActionPerformed(evt);
            }
        });

        jMenu1.add(jMenuItem2);

        jMenuBar1.add(jMenu1);

        jMenu2.setMnemonic('H');
        jMenu2.setText("Help");
        jMenuItem3.setMnemonic('A');
        jMenuItem3.setText("About");
        jMenuItem3.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/imsl/demo/RandomGen/Help16.gif")));
        jMenuItem3.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItem3ActionPerformed(evt);
            }
        });

        jMenu2.add(jMenuItem3);

        jMenuBar1.add(jMenu2);

        setJMenuBar(jMenuBar1);

        pack();
    }//GEN-END:initComponents

    private void jTextField1FocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_jTextField1FocusLost
        jTextField1.postActionEvent();
    }//GEN-LAST:event_jTextField1FocusLost

    private void jTextField1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jTextField1ActionPerformed
        numPoints = new Integer(jTextField1.getText().trim()).intValue();
        if (!textUpdateFlag)
            updateChart();
    }//GEN-LAST:event_jTextField1ActionPerformed
    
    private void jTextField2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jTextField2ActionPerformed
        numBins = new Integer(jTextField2.getText().trim()).intValue();
        if (!textUpdateFlag)
            updateChart();
    }//GEN-LAST:event_jTextField2ActionPerformed
        
    private void jMenuItem3ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItem3ActionPerformed
        // Help -> About
        String about = "This demonstration extends javax.swing.JFrame instead of \n" +
            "com.imsl.chart.JFrameChart like most of the other demos. \n" +
            "Therefore, you do not have access to the standard Print \n" +
            "and About menus that JFrameChart provides. However, that \n" +
            "functionality is easily duplicated, as it is here.";
        javax.swing.JOptionPane.showMessageDialog(this, about, "About", javax.swing.JOptionPane.INFORMATION_MESSAGE);
    }//GEN-LAST:event_jMenuItem3ActionPerformed
    
    private void jMenuItem1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItem1ActionPerformed
        // File -> Print
        java.awt.print.PrinterJob printJob = java.awt.print.PrinterJob.getPrinterJob();
        Chart chart = displayArea.getChart();
        printJob.setPrintable(chart);
        if (printJob.printDialog()){
            try {
                printJob.print();
            } catch (Exception e) {
                javax.swing.JOptionPane.showMessageDialog(this, e.getMessage(), "Exception", javax.swing.JOptionPane.ERROR_MESSAGE);
                e.printStackTrace();
            }
        }
    }//GEN-LAST:event_jMenuItem1ActionPerformed
    
    private void jMenuItem2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItem2ActionPerformed
        // File -> Exit
        System.exit(0);
    }//GEN-LAST:event_jMenuItem2ActionPerformed
    
    private void methodActionPerformed(String eventname) {
        textUpdateFlag = true;
        //jTextField1.postActionEvent();
        jTextField2.postActionEvent();
        textUpdateFlag = false;
        for(int i=0; i<numDist; i++){
            if(!eventname.equals(rname[i]))
                rb[i].setSelected(false);
            else {
                rb[i].setSelected(true);
                randomK = i;
            }
        }
        updateChart();
    }

    private void updateChart() {
        displayArea.setChart(new Chart());
        Chart chart = displayArea.getChart();
        String output = setup(chart, numPoints, numBins);
        if (!displayFrame.isVisible()) {
            displayFrame.setVisible(true);
        }
        displayFrame.repaint();
        jTextArea1.setText(output);
    }        
    
    // ++++++++++ setup method ++++++++++ //
    // ++  Create Histgram bar graph   ++ //
    // ++++++++++++++++++++++++++++++++++ //
    private String setup(Chart chart, int numPoints, int numBins) {
        bar = null;
        AxisXY axis = new AxisXY(chart);
        double v[] =  new double[numPoints];
        
        //  Generate some random data
        Random r = new Random();
        String x[] = new String[numBins];
        double y[] = new double[numBins];
        
        // -- Calc. Histgram data : y --
        for (int kitem = 0; kitem < numBins; kitem++) y[kitem]=0;

        double maxv = -10000;
        double minv = 10000;
        if (randomK != 20) {
            v = new double[numPoints];
            for (int i = 0; i < numPoints; i++) { // -- Max/Min value --
                v[i] = randomValue(r);
                if (maxv < v[i]) maxv=v[i];
                if (minv > v[i]) minv=v[i];
            }
        } else {
            double a[][] = {{ 1, -3,  2},{-3, 10, -5},{ 2, -5,  6}};
            try {
                Cholesky matrix = new Cholesky(a);
                int k = 3;
                v = r.nextMultivariateNormal(k, matrix);
                for (int i = 0; i < v.length; i++) {
                    if (v[i] < minv) minv=v[i];
                    if (v[i] > maxv) maxv=v[i];
                }
            } catch (Exception e) {
                javax.swing.JOptionPane.showMessageDialog(this, e.getMessage(), "Exception", javax.swing.JOptionPane.ERROR_MESSAGE);
                e.printStackTrace();
            }
        }
        
        double wx = (maxv-minv)/numBins;
        for (int kitem = 0; kitem < v.length; kitem++) {
            int i;
            if (maxv == v[kitem]){
                i = numBins-1;
            } else {
                i = (int) ((v[kitem]-minv)/wx);
            }
            y[i] = y[i] + 1;
        }

        //  Create an instance of a Bar Chart
        bar = new Bar(axis, y);

        chart.getChartTitle().setTitle(rname[randomK]+" Random Distribution");
        chart.getChartTitle().setFontStyle(java.awt.Font.BOLD);
        bar.setFillOutlineType(Bar.FILL_TYPE_SOLID);
        bar.getBarSet(0).setFillColor(Color.red);
        
        // Setup the X axis for a labeled bar chart.
        String spacer = " : ";
        String labels[] = new String[numBins];
        java.text.DecimalFormat df = new java.text.DecimalFormat();
        if (randomK != 15) {
            df.applyPattern("##0.00");
        } else {    // special format for logNormal
            df.applyPattern("0.0000");
        }
        labels[0] = String.valueOf(df.format(minv)) + spacer + String.valueOf(df.format(minv+wx));
        for (int i = 1; i < numBins-1; i++) {
            labels[i] = String.valueOf(df.format(minv + i*wx)) + spacer + String.valueOf(df.format(minv + (i+1)*wx));
        }
        labels[numBins-1] = String.valueOf(df.format(maxv-wx)) + spacer + String.valueOf(df.format(maxv));
        
        bar.setLabels(labels, Data.BAR_TYPE_VERTICAL);
        axis.getAxisX().getAxisLabel().setTextAngle(90);
        axis.getAxisY().getAxisTitle().setTitle("Number\n");
        axis.setViewport(0.1,0.95,0.1,0.8);
        if (randomK != 20) {
            axis.getAxisY().setTextFormat(new java.text.DecimalFormat("###0"));
        } else {
            axis.getAxisY().setTextFormat(new java.text.DecimalFormat("#0.0"));
        }

        // +++++ Print Random Name, Sample No. MAX, MIN +++++
        StringBuffer sb = new StringBuffer();
        sb.append("Random Distribution: "+rname[randomK]+"\n");
        if (randomK != 20) {
            sb.append("   # Samples: "+numPoints+"\n");
            sb.append("   # Bins: "+numBins+"\n");
        } else {
            sb.append("   Matrix: a[ ][ ] = {{ 1, -3,  2},{-3, 10, -5},{ 2, -5,  6}}\n");
        }
        sb.append("   Max Value: "+maxv+"\n");
        sb.append("   Min Value: "+minv+"\n");
        return sb.toString();
    }
    
    // ++++++++++ randomValue ++++++++++ //
    // ++  Create next Random value   ++ //
    // +++++++++++++++++++++++++++++++++ //
    double randomValue(Random r) {
        double nr = 0.0;
        if (randomK == 0) nr = r.nextDouble();
        if (randomK == 1) nr = r.nextBeta(1.0d, 0.5d);
        if (randomK == 2) nr = r.nextNormal();
        if (randomK == 3) nr = r.nextNormalAR();
        if (randomK == 4) nr = r.nextBinomial(5, 0.5d);
        if (randomK == 5) nr = r.nextCauchy();
        if (randomK == 6) nr = r.nextChiSquared(5);
        if (randomK == 7) nr = r.nextGamma(0.5);
        if (randomK == 8) nr = r.nextGeometric(0.5);
        if (randomK == 9) nr = r.nextHypergeometric(5, 5, 11);
        if (randomK == 10) nr = r.nextLogarithmic(0.5d);
        if (randomK == 11) nr = r.nextNegativeBinomial(0.5d, 0.5d);
        if (randomK == 12) nr = r.nextPoisson(10d);
        if (randomK == 13) nr = r.nextExponential();
        if (randomK == 14) nr = r.nextExponentialMix(30d, 10d, 0.5d);
        if (randomK == 15) nr = r.nextLogNormal(0d, .001d);
        if (randomK == 16) nr = r.nextTriangular();
        if (randomK == 17) nr = r.nextStudentsT(5.0d);
        if (randomK == 18) nr = r.nextVonMises(1.0e-7d);
        if (randomK == 19) nr = r.nextWeibull(5d);
        return nr;
    }
    
    // ++++++++++ set_rname method ++++++++++ //
    // ++  Set 21 Random names.            ++ //
    // ++++++++++++++++++++++++++++++++++++++ //
    public void set_rname(){
        rname[0]  = "Standard Pseudo";
        rname[1]  = "Beta";
        rname[2]  = "Normal";
        rname[3]  = "NormalAR";
        rname[4]  = "Binomial";
        rname[5]  = "Cauchy";
        rname[6]  = "ChiSquare";
        rname[7]  = "Gamma";
        rname[8]  = "Geometric";
        rname[9]  = "Hypergeometric";
        rname[10] = "Logarithmic";
        rname[11] = "NegativeBinomial";
        rname[12] = "Poisson";
        rname[13] = "Exponential";
        rname[14] = "ExponentialMix";
        rname[15] = "LogNormal";
        rname[16] = "Triangular";
        rname[17] = "StudentT";
        rname[18] = "VonMises";
        rname[19] = "Weibull";
        rname[20] = "MultivariateNormal";
    }
    
    /** Exit the Application */
    private void exitForm(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_exitForm
        setVisible(false);
        displayFrame.setVisible(false);
        displayFrame.dispose();
        dispose();
    }//GEN-LAST:event_exitForm
    
    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        boolean exitOnClose = true;
        if (args.length > 0  && args[0].equals("-noexit")) {
            exitOnClose = false;
        }
        new RandomGen(exitOnClose).show();
    }
    
    
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JPanel jPanel4;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JMenuItem jMenuItem2;
    private javax.swing.JSeparator jSeparator;
    private javax.swing.JMenu jMenu2;
    private javax.swing.JPanel jPanel3;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JMenuItem jMenuItem3;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JMenuItem jMenuItem1;
    private javax.swing.JTextArea jTextArea1;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JTextField jTextField2;
    private javax.swing.JMenu jMenu1;
    private javax.swing.JTextField jTextField1;
    private javax.swing.JMenuBar jMenuBar1;
    // End of variables declaration//GEN-END:variables
}