/*
 * TuningDialog.java
 *
 * Created on 10. März 2005, 14:23
 */

package org.rosuda.JClaR;

import java.awt.Dimension;
import javax.swing.ImageIcon;
import javax.swing.JFrame;


/**
 * A dialog for tunig the variables, i.e. finding the best values within a given range.
 * @author Tobias Wichtrey
 */
public final class TuningDialog extends javax.swing.JDialog {
    
    //#T#O#D#O#: Let user change the ranges interactively.
    
    private boolean setvalues=false;
    private RserveConnection rcon;
    private Data data;
    private String variable;
    private Tune tune;
    
    private DoubleTuneVariablePanel panCost;
    private DoubleTuneVariablePanel panNu;
    private IntegerTuneVariablePanel panDegree;
    private DoubleTuneVariablePanel panCoef0;
    private DoubleTuneVariablePanel panGamma;
    
    private int type;
    private int kernel;
    
    /**
     * Creates new form TuningDialog
     * @param parent The parent frame of this dialog. If parent is of class MainWindow, the values are transferred.
     * @param con The RConnection to do the tuning with.
     * @param type The type of SVM.
     * @param kernel
     */
    TuningDialog(final JFrame parent, final int type, final int kernel, final double minNu, final double maxNu) {
        
        //TODO: Fix layout of TuneVariablePanels and TuningDialog: Scaling!
        
        super(parent);
        rcon=RserveConnection.getRconnection();
        initComponents();
        
        this.type=type;
        this.kernel=kernel;        
        
        panCost = new DoubleTuneVariablePanel();
        panCost.setVariableName("Cost");
        panCost.setMin(0.001);
        panNu = new DoubleTuneVariablePanel();
        panNu.setVariableName("Nu");
        panNu.setMin(minNu);
        panNu.setMax(maxNu);
        panDegree = new IntegerTuneVariablePanel();
        panDegree.setVariableName("Degree");
        panDegree.setMin(1);
        panDegree.setValue(1);
        panCoef0 = new DoubleTuneVariablePanel();
        panCoef0.setVariableName("Coef0");
        panGamma = new DoubleTuneVariablePanel();
        panGamma.setVariableName("Gamma");
        panGamma.setMin(0.001);
        
        switch(type){
            case SVM.TYPE_C_CLASS:
            case SVM.TYPE_EPS_REGR:
                panTuneVariablePanels.add(panCost,0);
                break;
            default: // Nu-regression, nu-classification, one-classification
                panTuneVariablePanels.add(panNu,0);
                panTuneVariablePanels.add(panCost,0);
                break;
        }
        
        switch(kernel){
            case SVM.KERNEL_LINEAR:
                // no parameters
                break;
            case SVM.KERNEL_POLYNOMIAL:
                panTuneVariablePanels.add(panDegree,0);
                panTuneVariablePanels.add(panCoef0,0);
                panTuneVariablePanels.add(panGamma,0);
                break;
            case SVM.KERNEL_RADIAL:
                panTuneVariablePanels.add(panGamma,0);
                break;
            default: // sigmoid
                panTuneVariablePanels.add(panCoef0,0);
                panTuneVariablePanels.add(panGamma,0);
                break;
        }
        pack();
    }
    
    /** 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() {
        panMain2 = new javax.swing.JPanel();
        jPanel3 = new javax.swing.JPanel();
        butBack = new javax.swing.JButton();
        butOK = new javax.swing.JButton();
        jcbSetparam = new javax.swing.JCheckBox();
        jtaResult = new javax.swing.JTextArea();
        lblPlot = new javax.swing.JLabel();
        panMain1 = new javax.swing.JPanel();
        panTuneVariablePanels = new javax.swing.JPanel();
        jPanel2 = new javax.swing.JPanel();
        butTune = new javax.swing.JButton();
        butCancel = new javax.swing.JButton();
        butHelp = new javax.swing.JButton();

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

        butBack.setText("Back");
        butBack.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                butBackActionPerformed(evt);
            }
        });

        jPanel3.add(butBack);

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

        jPanel3.add(butOK);

        jcbSetparam.setSelected(true);
        jcbSetparam.setText("set Parameters to optimal values");
        jPanel3.add(jcbSetparam);

        panMain2.add(jPanel3, java.awt.BorderLayout.SOUTH);

        jtaResult.setEditable(false);
        jtaResult.setMaximumSize(new java.awt.Dimension(350, 2147483647));
        jtaResult.setPreferredSize(new java.awt.Dimension(350, 100));
        panMain2.add(jtaResult, java.awt.BorderLayout.NORTH);

        panMain2.add(lblPlot, java.awt.BorderLayout.CENTER);

        setDefaultCloseOperation(javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE);
        setTitle("Variable tuning dialog");
        setModal(true);
        panMain1.setLayout(new java.awt.GridLayout(2, 0));

        panTuneVariablePanels.setLayout(new javax.swing.BoxLayout(panTuneVariablePanels, javax.swing.BoxLayout.Y_AXIS));

        panMain1.add(panTuneVariablePanels);

        butTune.setMnemonic('t');
        butTune.setText("Tune");
        butTune.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                butTuneActionPerformed(evt);
            }
        });

        jPanel2.add(butTune);

        butCancel.setMnemonic('c');
        butCancel.setText("Cancel");
        butCancel.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                butCancelActionPerformed(evt);
            }
        });

        jPanel2.add(butCancel);

        butHelp.setMnemonic('h');
        butHelp.setText("Help");
        butHelp.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                butHelpActionPerformed(evt);
            }
        });

        jPanel2.add(butHelp);

        panMain1.add(jPanel2);

        getContentPane().add(panMain1, java.awt.BorderLayout.CENTER);

        pack();
    }
    // </editor-fold>//GEN-END:initComponents
    
    private void butHelpActionPerformed(final java.awt.event.ActionEvent evt) {//GEN-FIRST:event_butHelpActionPerformed
        HelpDialog.show(this,"fixed: The variable will not be tuned but fixed at the given value.\n" +
                "tune: The variable will be tuned within the given ranges in steps with size \"by\".");
    }//GEN-LAST:event_butHelpActionPerformed
    
    private void butOKActionPerformed(final java.awt.event.ActionEvent evt) {//GEN-FIRST:event_butOKActionPerformed
        setvalues = jcbSetparam.isSelected();
        dispose();
    }//GEN-LAST:event_butOKActionPerformed
    
    private void butBackActionPerformed(final java.awt.event.ActionEvent evt) {//GEN-FIRST:event_butBackActionPerformed
        getContentPane().remove(panMain2);
        getContentPane().add(panMain1);
        lblPlot.setIcon(null);
        pack();
    }//GEN-LAST:event_butBackActionPerformed
    
    private void butCancelActionPerformed(final java.awt.event.ActionEvent evt) {//GEN-FIRST:event_butCancelActionPerformed
        dispose();
    }//GEN-LAST:event_butCancelActionPerformed
    
    private void butTuneActionPerformed(final java.awt.event.ActionEvent evt) {//GEN-FIRST:event_butTuneActionPerformed
        if(!panCost.getTune() && !panGamma.getTune() && !panDegree.getTune() && !panNu.getTune() && !panCoef0.getTune()){
            ErrorDialog.show(this, "Please select at least one parameter to tune.");
            return;
        }
        
        tune = new Tune(data);
        tune.setFromCost(panCost.getFrom());
        tune.setToCost(panCost.getTo());
        tune.setByCost(panCost.getSteps());
        tune.setTuneCost(panCost.getTune());
        tune.setFixCost(panCost.getFix());
        tune.setFromGamma(panGamma.getFrom());
        tune.setToGamma(panGamma.getTo());
        tune.setByGamma(panGamma.getSteps());
        tune.setTuneGamma(panGamma.getTune());
        tune.setFixGamma(panGamma.getFix());
        tune.setFromDegree(panDegree.getFrom());
        tune.setToDegree(panDegree.getTo());
        tune.setByDegree(panDegree.getSteps());
        tune.setTuneDegree(panDegree.getTune());
        tune.setFixDegree(panDegree.getFix());
        tune.setFromNu(panNu.getFrom());
        tune.setToNu(panNu.getTo());
        tune.setByNu(panNu.getSteps());
        tune.setTuneNu(panNu.getTune());
        tune.setFixNu(panNu.getFix());
        tune.setFromCoef0(panCoef0.getFrom());
        tune.setToCoef0(panCoef0.getTo());
        tune.setByCoef0(panCoef0.getSteps());
        tune.setTuneCoef0(panCoef0.getTune());
        tune.setFixCoef0(panCoef0.getFix());
        
        tune.setVariable(variable);
        
        tune.setKernel(kernel);
        tune.setType(type);
        
        tune.tune();
        jtaResult.setText(tune.toString());
        
        getContentPane().remove(panMain1);
        getContentPane().add(panMain2);
        
        if(tune.getNumberOfTunedParameters()<=2) {
            lblPlot.setIcon(new ImageIcon(tune.plot().plot(375,375)));
            lblPlot.setPreferredSize(new Dimension(375,375));
        } else lblPlot.setPreferredSize(new Dimension(0,0));
        
        jtaResult.setPreferredSize(new Dimension(375,(int)jtaResult.getMinimumSize().getHeight()));
        
        pack();
    }//GEN-LAST:event_butTuneActionPerformed
    
    /**
     * Whether the variables should be set to the tuning result or not
     * @return <CODE>true</CODE> if values should be set, <CODE>false</CODE> otherwise
     */
    boolean getSetvalues(){
        return setvalues;
    }
    
    Tune getTune(){
        return tune;
    }
    
    void setData(final Data data) {
        this.data = data;
    }
    
    void setVariable(final String variable) {
        this.variable = variable;
    }
    
    void setFixGamma(final double fixGamma) {
        panGamma.setValue(fixGamma);
    }
    
    void setFixNu(final double fixNu) {
        panNu.setValue(fixNu);
    }
    
    void setFixCoef0(final double fixCoef0) {
        panCoef0.setValue(fixCoef0);
    }
    
    void setFixCost(final double fixCost) {
        panCost.setValue(fixCost);
    }
    
    void setFixDegree(final int fixDegree) {
        panDegree.setValue(fixDegree);
    }
    
    void setDefaultRanges(){
        panCost.setDefaultFromToRange();
        panCoef0.setDefaultFromToRange();
        panGamma.setDefaultFromToRange();
        panNu.setDefaultFromToRange();
        panDegree.setDefaultFromToRange();
    }
    
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton butBack;
    private javax.swing.JButton butCancel;
    private javax.swing.JButton butHelp;
    private javax.swing.JButton butOK;
    private javax.swing.JButton butTune;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JPanel jPanel3;
    private javax.swing.JCheckBox jcbSetparam;
    private javax.swing.JTextArea jtaResult;
    private javax.swing.JLabel lblPlot;
    private javax.swing.JPanel panMain1;
    private javax.swing.JPanel panMain2;
    private javax.swing.JPanel panTuneVariablePanels;
    // End of variables declaration//GEN-END:variables
    
}
