/*
 * Copyright (c) 2014 Paul Scherrer Institute. All rights reserved.
 */

import ch.psi.pshell.plot.Plot;
import ch.psi.pshell.ui.App;
import ch.psi.pshell.ui.Panel;
import ch.psi.utils.State;
import java.awt.Component;
import java.util.HashMap;
import java.util.List;

/**
 *
 */
public class Correlation extends Panel {

    public Correlation() {
        initComponents();
        this.setPersistedComponents(new Component[]{textDevX, textDevY, spinnerInterval, spinnerWindow, checkBS});
        plot.getAxis(Plot.AxisId.X).setLabel(null);
        plot.getAxis(Plot.AxisId.Y).setLabel(null);
    }

     //Overridable callbacks
    @Override
    public void onInitialize(int runCount) {
        super.onInitialize(runCount);
        this.startTimer(100, 10);
        if (App.hasArgument("dx")) {
                textDevX.setText(App.getArgumentValue("dx"));
        }
        if (App.hasArgument("dy")) {
                textDevY.setText(App.getArgumentValue("dy"));
        }        
        try{
            if (App.hasArgument("bs")) {
                checkBS.setSelected(Boolean.valueOf(App.getArgumentValue("bs")));
            }        
        } catch (Exception ex){            
           System.err.println(ex.getMessage());
        }
        try{
            if (App.hasArgument("interval")) {
                spinnerInterval.setValue(Double.valueOf(App.getArgumentValue("interval")));
            }        
        } catch (Exception ex){            
            System.err.println(ex.getMessage());
        }
        try{
            if (App.hasArgument("window")) {
                spinnerWindow.setValue(Integer.valueOf(App.getArgumentValue("window")));
            }        
        } catch (Exception ex){            
            System.err.println(ex.getMessage());
        }                    
    }
    
    @Override
    protected void onTimer(){
        if (isRunning()){
            updateResults();
        }
    }
    
    //DecimalFormat formatter = new DecimalFormat("0.##E0");
    void updateResults(){
        try{
            textCorrelation.setText(String.format("%1.4f", Double.valueOf((Double)getContext().getInterpreterVariable("corr"))));            
        } catch (Exception ex){
            textCorrelation.setText("");
        }
        
        if (checkLinear.isSelected()){
            try{
                List pars = (List)getContext().getInterpreterVariable("pars_lin");            
                //textLinear.setText(String.format("%1.3fx%+1.3f", (Double)(pars.get(1)),  (Double)(pars.get(0))));            
                textLinear.setText(String.format("%1.6gx%+1.6g",pars.get(1),  pars.get(0)));            
            } catch (Exception ex){
                textLinear.setText("");
            }        
        }
        
        if (checkQuadratic.isSelected()){
            try{
                List pars = (List)getContext().getInterpreterVariable("pars_quad");            
                //textQuadratic.setText(String.format("%1.2fx\u00B2 %+1.2fx%+1.2f", (Double)(pars.get(0)), (Double)(pars.get(1)),  (Double)(pars.get(0))));            
                textQuadratic.setText(String.format("%1.3gx\u00B2%+1.3gx%+1.3g", pars.get(0), pars.get(1), pars.get(0)));            
                //textQuadratic.setText(formatter.format(pars.get(2))+ formatter.format(pars.get(1)) + formatter.format(pars.get(0)));            

            } catch (Exception ex){
                textQuadratic.setText("");
            }        
        }        
    }

    @Override
    public void onStateChange(State state, State former) {
        buttonStart.setEnabled((state==State.Ready) || (state==State.Busy));
        if (isRunning()){
            if (state==State.Ready){
                buttonStart.setText("Start");
            }
        } else {
            if (state==State.Busy){
                buttonStart.setText("Stop");
            }
        }
        textDevX.setEnabled(state==State.Ready);
        textDevY.setEnabled(state==State.Ready);
        spinnerInterval.setEnabled(state==State.Ready);
        spinnerWindow.setEnabled(state==State.Ready);        
        checkBS.setEnabled(state==State.Ready);        
        checkLinear.setEnabled(state==State.Ready);        
        checkQuadratic.setEnabled(state==State.Ready);        
        
        if ((former==State.Initializing) && (state == State.Ready)){
            if (App.hasArgument("start")) {
                buttonStartActionPerformed(null);
            }        
        }
        
    }
    
    boolean isRunning(){
        return buttonStart.getText().equals("Stop");
    }

    @Override
    public void onExecutedFile(String fileName, Object result) {
    }

    
    //Callback to perform update - in event thread
    @Override
    protected void doUpdate() {
    }

    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        plot = new ch.psi.pshell.plot.LinePlotJFree();
        jPanel1 = new javax.swing.JPanel();
        jLabel1 = new javax.swing.JLabel();
        textDevX = new javax.swing.JTextField();
        textDevY = new javax.swing.JTextField();
        jLabel2 = new javax.swing.JLabel();
        jLabel3 = new javax.swing.JLabel();
        spinnerInterval = new javax.swing.JSpinner();
        jLabel4 = new javax.swing.JLabel();
        spinnerWindow = new javax.swing.JSpinner();
        buttonStart = new javax.swing.JButton();
        jLabel5 = new javax.swing.JLabel();
        textCorrelation = new javax.swing.JTextField();
        checkBS = new javax.swing.JCheckBox();
        jLabel6 = new javax.swing.JLabel();
        textLinear = new javax.swing.JTextField();
        jLabel7 = new javax.swing.JLabel();
        textQuadratic = new javax.swing.JTextField();
        checkLinear = new javax.swing.JCheckBox();
        checkQuadratic = new javax.swing.JCheckBox();

        plot.setTitle("");

        jLabel1.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING);
        jLabel1.setText("X device:");

        jLabel2.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING);
        jLabel2.setText("Y device:");

        jLabel3.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING);
        jLabel3.setText("Interval (s):");

        spinnerInterval.setModel(new javax.swing.SpinnerNumberModel(Double.valueOf(0.1d), Double.valueOf(0.001d), null, Double.valueOf(1.0d)));

        jLabel4.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING);
        jLabel4.setText("Window size:");

        spinnerWindow.setModel(new javax.swing.SpinnerNumberModel(Integer.valueOf(50), Integer.valueOf(3), null, Integer.valueOf(1)));

        buttonStart.setText("Start");
        buttonStart.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                buttonStartActionPerformed(evt);
            }
        });

        jLabel5.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
        jLabel5.setText("Correlation:");

        textCorrelation.setEditable(false);
        textCorrelation.setHorizontalAlignment(javax.swing.JTextField.CENTER);

        checkBS.setText("Beam synchronous");

        jLabel6.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
        jLabel6.setText("Liner fit:");

        textLinear.setEditable(false);
        textLinear.setHorizontalAlignment(javax.swing.JTextField.CENTER);

        jLabel7.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
        jLabel7.setText("Quadratric fit:");

        textQuadratic.setEditable(false);
        textQuadratic.setHorizontalAlignment(javax.swing.JTextField.CENTER);

        checkLinear.setSelected(true);
        checkLinear.setText("Linear fit");

        checkQuadratic.setText("Quadratic fit");

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jLabel7, javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(jLabel6, javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(jLabel5, javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(jLabel3, javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(jLabel2, javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(jLabel1, javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(jLabel4, javax.swing.GroupLayout.Alignment.TRAILING))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(textDevX, javax.swing.GroupLayout.DEFAULT_SIZE, 250, Short.MAX_VALUE)
                    .addComponent(textDevY, javax.swing.GroupLayout.DEFAULT_SIZE, 250, Short.MAX_VALUE)
                    .addComponent(textCorrelation, javax.swing.GroupLayout.DEFAULT_SIZE, 250, Short.MAX_VALUE)
                    .addComponent(spinnerInterval, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(spinnerWindow, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(checkBS)
                    .addComponent(textLinear, javax.swing.GroupLayout.DEFAULT_SIZE, 250, Short.MAX_VALUE)
                    .addComponent(textQuadratic, javax.swing.GroupLayout.DEFAULT_SIZE, 250, Short.MAX_VALUE)
                    .addComponent(checkLinear)
                    .addComponent(checkQuadratic))
                .addGap(0, 0, Short.MAX_VALUE))
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addComponent(buttonStart, javax.swing.GroupLayout.PREFERRED_SIZE, 189, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        jPanel1Layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {jLabel1, jLabel2, jLabel3, jLabel4});

        jPanel1Layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {spinnerInterval, spinnerWindow});

        jPanel1Layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {jLabel5, jLabel6, jLabel7});

        jPanel1Layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {textCorrelation, textDevX, textDevY, textLinear, textQuadratic});

        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel1)
                    .addComponent(textDevX, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel2)
                    .addComponent(textDevY, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(checkBS)
                .addGap(18, 18, 18)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel3)
                    .addComponent(spinnerInterval, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel4)
                    .addComponent(spinnerWindow, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addGap(18, 18, 18)
                .addComponent(checkLinear)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(checkQuadratic)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 42, Short.MAX_VALUE)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER)
                    .addComponent(textCorrelation, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel5))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER)
                    .addComponent(jLabel6)
                    .addComponent(textLinear, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER)
                    .addComponent(jLabel7)
                    .addComponent(textQuadratic, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 42, Short.MAX_VALUE)
                .addComponent(buttonStart)
                .addGap(45, 45, 45))
        );

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(plot, javax.swing.GroupLayout.DEFAULT_SIZE, 371, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(plot, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addContainerGap())))
        );
    }// </editor-fold>//GEN-END:initComponents

    private void buttonStartActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonStartActionPerformed
        try {
            if (isRunning()){
                abort();
                updateResults();
                //buttonStart.setText("Start");
            } else {
                textCorrelation.setText("");
                textLinear.setText("");
                textQuadratic.setText("");
                HashMap args = new HashMap();
                args.put("dx", textDevX.getText());
                args.put("dy", textDevY.getText());
                args.put("interval", spinnerInterval.getValue());
                args.put("window", spinnerWindow.getValue());
                args.put("bs", checkBS.isSelected());
                args.put("linear_fit", checkLinear.isSelected());
                args.put("quadratic_fit", checkQuadratic.isSelected());

                args.put("p", plot);
                runAsync("Correlation/Correlation", args).handle((ok, ex) -> {
                    if (ex != null) {
                        ex.printStackTrace();
                    }            
                    return ok;
                }); 
                ///buttonStart.setText("Stop");
            }

        } catch (Exception ex) {
            showException(ex);
        }        
    }//GEN-LAST:event_buttonStartActionPerformed

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton buttonStart;
    private javax.swing.JCheckBox checkBS;
    private javax.swing.JCheckBox checkLinear;
    private javax.swing.JCheckBox checkQuadratic;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JLabel jLabel5;
    private javax.swing.JLabel jLabel6;
    private javax.swing.JLabel jLabel7;
    private javax.swing.JPanel jPanel1;
    private ch.psi.pshell.plot.LinePlotJFree plot;
    private javax.swing.JSpinner spinnerInterval;
    private javax.swing.JSpinner spinnerWindow;
    private javax.swing.JTextField textCorrelation;
    private javax.swing.JTextField textDevX;
    private javax.swing.JTextField textDevY;
    private javax.swing.JTextField textLinear;
    private javax.swing.JTextField textQuadratic;
    // End of variables declaration//GEN-END:variables
}
