/*
 * -------------------------------------------------------------------------
 *      $Id: SampleSize.java,v 1.3 2004/05/26 19:06:49 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.Samples;
import javax.swing.*;
import javax.swing.event.*;
import java.awt.event.*;
import java.text.DecimalFormat;
import com.imsl.stat.*;
import com.imsl.math.JMath;
import com.imsl.chart.*;


/**
 *
 * @author     Gregory D. Rodd
 * @created    October 16, 2002
*/
public class SampleSize extends JFrameChart implements ActionListener, ChangeListener, MouseListener, MouseMotionListener {

    private Chart chart;
    private AxisXY axis;
    private Data successData, powerData, tolerData;
    private JLabel confLabel;
    private JSlider slider0, slider1, slider2;
    private JTextField alphaField, sigmaField, widthField, displayField;
    private double[] xrange, x, current;
    private double y[][];

    static final private int numSample = 500;
    static private String title[] = {"Power/OC Curve", "Success Probability", "Tolerance"};


    public SampleSize(boolean exitOnClose) {
        setTitle("Sample Size");
        if (!exitOnClose) {
            // remove the WindowListener,  installed by JFrameChart, 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]);
            }
        }

        // Set default values.
        chart = getChart();
        axis = new AxisXY(chart);
        axis.getAxisX().getAxisTitle().setTitle("Sample Size");
        axis.getAxisY().getAxisTitle().setTitle("Probability");
        axis.getAxisY().setWindow(0.0, 1.00);
        axis.getAxisX().setAutoscaleInput(AxisXY.AUTOSCALE_OFF);

        current = new double[2];
        double minSampleSize = 4.0;
        double xrange[] = {minSampleSize,(double)(numSample+minSampleSize-1)};
        x = new double[numSample];
        for (int i = 0; i < numSample; i++) {
            x[i] = i + minSampleSize;
        };
        y = new double[3][x.length];

        // Add MouseListener and MouseMotionListener to chart panel.
        chart.getLegend().setPaint(true);
        chart.getLegend().setViewport(0.78,0.0,0.2,0.2);
        getPanel().addMouseListener(this);
        getPanel().addMouseMotionListener(this);

        // Create components in control panel.
        JButton reset = new JButton("Reset");
        reset.addActionListener(this);

        confLabel = new JLabel("Confidence = 0.95", JLabel.LEFT);

        JLabel dummyLabel = new JLabel("  ", JLabel.CENTER);

        JLabel alphaLabel = new JLabel("Alpha", JLabel.CENTER);
        alphaField = new JTextField("0.05", 6);
        alphaField.setEditable(false);
        slider0 = new JSlider(200, 499, 450);
        slider0.setPaintTicks(true);
        slider0.setPaintLabels(false);
        slider0.setMajorTickSpacing(50);
        slider0.setMinorTickSpacing(10);
        slider0.setSnapToTicks(true);
        slider0.addChangeListener(this);

        JLabel deltaLabel = new JLabel("Delta|CI Width", JLabel.CENTER);
        widthField = new JTextField("1.00", 6);
        widthField.setEditable(false);
        slider1 = new JSlider(1, 500, 100);
        slider1.setPaintTicks(true);
        slider1.setPaintLabels(false);
        slider1.setMajorTickSpacing(80);
        slider1.setMinorTickSpacing(20);
        slider1.addChangeListener(this);

        JLabel sigmaLabel = new JLabel("Standard Deviation", JLabel.CENTER);
        sigmaField = new JTextField("1.00", 6);
        sigmaField.setEditable(false);
        slider2 = new JSlider(1, 500, 100);
        slider2.setPaintTicks(true);
        slider2.setPaintLabels(false);
        slider2.setMajorTickSpacing(80);
        slider2.setMinorTickSpacing(20);
        slider2.addChangeListener(this);

        JPanel buttonPanel = new JPanel();
        buttonPanel.setLayout(new java.awt.GridLayout(3,3,3,3));
        // First Five Buttons
        buttonPanel.add(alphaLabel);
        buttonPanel.add(slider0);
        buttonPanel.add(alphaField);
        buttonPanel.add(confLabel);
        // Second Five Buttons
        buttonPanel.add(deltaLabel);
        buttonPanel.add(slider1);
        buttonPanel.add(widthField);
        buttonPanel.add(dummyLabel);
        // Third Five buttons
        buttonPanel.add(sigmaLabel);
        buttonPanel.add(slider2);
        buttonPanel.add(sigmaField);
        buttonPanel.add(reset);

        // Create the display panel
        JPanel displayPanel = new JPanel();

        displayField = new JTextField("Current position:  Sample Size = ??  Probability = ??", 53);
        displayField.setEditable(false);
        displayPanel.add(displayField);

        java.awt.Container cp = getContentPane();
        cp.add(buttonPanel, java.awt.BorderLayout.NORTH);
        cp.add(displayPanel, java.awt.BorderLayout.SOUTH);

        drawGraph();

        com.imsl.demo.gallery.Describe des = new com.imsl.demo.gallery.Describe(this, "/com/imsl/demo/Samples/Samples.html");
        des.show();
        java.awt.Dimension dess = des.getSize();

        java.awt.Dimension ss = getToolkit().getScreenSize();
        int h = Math.min(ss.width/2, ss.height-dess.height-32);
        int w = (int)(h/.8);
        setSize(w, h);
        setLocation(ss.width-dess.width, dess.height);
        setResizable(false);
    }


    //  Get the description line.
    private String getDescription() {
        DecimalFormat nff = new DecimalFormat("0.000");
        DecimalFormat nfi = new DecimalFormat("##0");
        StringBuffer sb = new StringBuffer();
        sb.append("Cursor At:  Sample Size = " + nfi.format(Math.ceil(current[0]))+
            "  Probability = " + nff.format(current[1]));
        return sb.toString();
    }

    private double CILength(double N, double alph, double gam, double sig) {
        return (JMath.sqrt(Cdf.inverseChi(gam, (N-1)))* 2.0 * sig *
        Cdf.inverseStudentsT((1.0 - (0.5 * alph) ),(N-1))) /
        JMath.sqrt(N * (N-1));
    }
    private double tolerProb(double N, double alph, double Lenth, double sig) {
        double Tsq;
        Tsq = Cdf.inverseStudentsT( 1.0 - (0.5 * alph), N - 1);
        Tsq = Tsq * Tsq;
        return (Cdf.chi((N*(N-1.0)*Lenth*Lenth*0.25/(sig * sig * Tsq)),N-1));
    }

    /*
     *      Probability of meeting objective
     */
    private double probSuccess(double N, double alph, double delt) {
        double A1 = 1.0 - (0.5 * alph);
        double T1 = Cdf.inverseStudentsT(A1,(N-1));
        double DN = delt * delt * N * (N - 1.0);
        return Cdf.chi(DN / (T1 * T1), (N-1));
    }


    private double powerR(double N, double alph, double delt, double sig) {
        double A1 = 1.0 - (0.5 * alph);
        double T1 = Cdf.inverseStudentsT(A1,(N-1));
        double bigDel = JMath.sqrt(N) * (delt / sig);
        double pHi = tncCdf.cdf(T1, N-1.0, -bigDel);
        double pLo = tncCdf.cdf(-T1, N-1.0, -bigDel);
        //   return pLo - pHi + 1.0;
        // 1 - Beta give the operating characteristic curve
        return (pHi - pLo);
    }

    // Draw the graph.
    private void drawGraph() {
        try {
            int num = slider0.getValue();
            double alpha = (500.0 - (double)num) / 1000.0;
            int num1 = slider1.getValue();
            double delta = (double)num1 / 100.0;
            int num2 = slider2.getValue();
            double sigma = (double)num2 / 100.0;

            int flat = -1;
            // Compute the probabilities data.
            for (int k = 0;  k < x.length;  k++) {
                y[0][k] = powerR(x[k], alpha, delta, sigma);
                y[1][k] = probSuccess(x[k], alpha, delta/sigma);
                y[2][k] = tolerProb(x[k], alpha, delta, sigma);
                if (flat == -1 && y[0][k] < 0.0005) {
                    flat = k;
                }
            }

            if (flat == -1) {
                axis.getAxisX().setWindow(0.00, x[x.length-1]);
            } else {
                axis.getAxisX().setWindow(0.00, x[flat]);
            }

            powerData = new Data(axis, x, y[0]);
            powerData.setTitle(title[0]);
            powerData.setDataType(Data.DATA_TYPE_LINE );
            powerData.setLineColor("darkGreen");

            successData = new Data(axis, x, y[1]);
            successData.setTitle(title[1]);
            successData.setDataType(Data.DATA_TYPE_LINE);
            successData.setLineColor("red");

            tolerData = new Data(axis, x, y[2]);
            tolerData.setTitle(title[2]);
            tolerData.setDataType(Data.DATA_TYPE_LINE );
            tolerData.setLineColor("blue");
        } catch (Exception e) {
        }
    }



    // Get the information from the interface and redraw the chart.
    private void update() {
        if (successData != null) successData.remove();
        if (powerData != null) powerData.remove();
        if (tolerData != null) tolerData.remove();
        drawGraph();
        repaint();
    }



    // Implement ActionListener for Reset Button
    public void actionPerformed(ActionEvent e) {
        confLabel.setText("Confidence = 0.95");
        alphaField.setText("0.05");
        widthField.setText("1.00");
        sigmaField.setText("1.00");
        slider0.setValue(450);
        slider1.setValue(100);
        slider2.setValue(100);
    }


    // Implement ChangeListener for Sliders
    public void stateChanged(ChangeEvent e) {
        // Derive conf from alpha slider value
        int num = slider0.getValue();
        double alpha = (500.0 - (double)num) / 1000.0;
        double conf  = 100.0 * (1.0 - alpha);
        int num1 = slider1.getValue();
        double delta = (double)num1 / 100.0;
        int num2 = slider2.getValue();
        double sigma = (double)num2 / 100.0;

        DecimalFormat nf = new DecimalFormat("0.00");
        alphaField.setText(nf.format(alpha));
        confLabel.setText("Confidence = "+nf.format(conf/100));
        widthField.setText(nf.format(delta));
        sigmaField.setText(nf.format(sigma));
        update();
    }



    // Implement MouseListener
    public void mouseClicked(MouseEvent e) {
    }

    public void mousePressed(MouseEvent e) {
    }

    public void mouseReleased(MouseEvent e) {
    }

    public void mouseEntered(MouseEvent e) {
        setCursor(new java.awt.Cursor(java.awt.Cursor.CROSSHAIR_CURSOR));
    }

    public void mouseExited(MouseEvent e) {
        setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
    }

    public void mouseDragged(MouseEvent e) {
    }

    public void mouseMoved(MouseEvent e) {
        // Update display information.
        axis.mapDeviceToUser(e.getX(), e.getY(), current);
        displayField.setText(getDescription());
    }

    public static void main(String args[]) {
        boolean exitOnClose = true;
        if (args.length > 0  && args[0].equals("-noexit")) {
            exitOnClose = false;
        }
        new SampleSize(exitOnClose).show();
    }
}