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

import ch.psi.pshell.core.Context.ContextStateException;
import ch.psi.pshell.data.PlotDescriptor;
import ch.psi.pshell.device.Device;
import ch.psi.pshell.device.DeviceAdapter;
import ch.psi.pshell.device.DeviceListener;
import ch.psi.pshell.epics.ChannelDoubleArray;
import ch.psi.pshell.epics.ChannelInteger;
import ch.psi.pshell.plot.LinePlot;
import ch.psi.pshell.plot.LinePlotBase;
import ch.psi.pshell.plot.LinePlotSeries;
import ch.psi.pshell.plot.Plot;
import ch.psi.pshell.ui.Panel;
import ch.psi.utils.Chrono;
import ch.psi.utils.State;
import ch.psi.utils.swing.SwingUtils;
import ch.psi.psaf.DsvEditor;
import ch.psi.psaf.Editor.EditorDialog;
import java.awt.Component;
import java.io.FileInputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Properties;
import java.util.logging.Level;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JLabel;

/**
 *
 */
public class EnergyScan extends Panel {

    ChannelDoubleArray data;
    ChannelDoubleArray edata;
    ChannelDoubleArray idata;
    ChannelDoubleArray fdata;
    ChannelInteger count;

    double[] offsets = new double[4];

    public EnergyScan() {
        initComponents();
        buttonDefaultsActionPerformed(null);
    }

    @Override
    public void onInitialize(int runCount) {
        super.onInitialize(runCount);

        count = (ChannelInteger) getContext().getDevicePool().getByName("count");
        data = (ChannelDoubleArray) getContext().getDevicePool().getByName("data");
        edata = (ChannelDoubleArray) getContext().getDevicePool().getByName("edata");
        idata = (ChannelDoubleArray) getContext().getDevicePool().getByName("idata");
        fdata = (ChannelDoubleArray) getContext().getDevicePool().getByName("fdata");

        getContext().getDevicePool().getByName("count").addListener(new DeviceAdapter() {
            @Override
            public void onValueChanged(Device device, Object value, Object former) {
                update();
            }
        });
        update();
        //loadConfig();
    }

    @Override
    public void onStart() {
        super.onStart();
        loadConfig();
    }
    
    @Override
    public void onStateChange(State state, State former) {
        setEnabled(state == State.Ready);
    }

    void stopScan() throws Exception {
        evalAsync("caput('START', 'STOP')");
    }

    long scanStartTimestamp;

    @Override
    public void onExecutedFile(String fileName, Object result) {
        try {
            switch (fileName) {
                case "EnergyScan":
                    if (result instanceof Exception) {
                        batchIndex = 0;
                        batch = null;
                        stopScan();
                        throw ((Exception) result);
                    }
                    if (batch != null) {
                        batchIndex++;
                        if (batchIndex >= batch.length) {
                            batchIndex = 0;
                            batch = null;
                        } else {
                            setMode(batch[batchIndex]);
                            run();
                        }
                    }
                    break;
            }
        } catch (Exception ex) {
            getLogger().log(Level.WARNING, null, ex);
            SwingUtils.showException(this, ex);
        }
    }

    @Override
    protected void doUpdate() {
        plot();
    }

    Path getConfigFile() {
        return Paths.get(getContext().getSetup().getConfigPath(), "energy_scan.properties");
    }

    enum Mode {

        plus,
        minus,
        lh,
        lv
    }

    Mode[] batch;
    int batchIndex;

    LinePlotBase scanPlot;
    LinePlotSeries scanSeries;

    @Override
    public void setEnabled(boolean value) {
        super.setEnabled(value);
        buttonExecute.setEnabled(value);
        comboSetup.setEnabled(value);
        comboRunType.setEnabled(value);
        buttonConfigure.setEnabled(value);
        textFile.setEnabled(value);
        textFolder.setEnabled(value);
        buttonDefaults.setEnabled(value);
        buttonPlot.setEnabled(value);
        checkParameterControls();
    }

    void checkParameterControls() {
        boolean enabled = isEnabled() && (comboRunType.getSelectedIndex() == 0);
        for (Component c : panelParameters.getComponents()) {
            if (!(c instanceof JLabel)) {
                c.setEnabled(enabled);
            }
        }
        spinnerAlpha.setEnabled(enabled && comboMode.getSelectedItem().equals("LINEAR"));
    }

    void plot() {
        try {
            if ((scanPlot != null) && (scanSeries != null) && scanPlot.isShowing() && (count != null)) {
                //buttonGroupPlot.getSelection().                    
                Integer c = count.take();
                if (c == null) {
                    scanSeries.clear();
                } else {
                    double[] ydata = null;
                    if (radioE.isSelected()) {
                        data.setSize(c);
                        ydata = data.read();
                    } else if (radioF.isSelected()) {
                        fdata.setSize(c);
                        ydata = fdata.read();
                    } else if (radioI0.isSelected()) {
                        idata.setSize(c);
                        ydata = idata.read();
                    } else if (radioTEY.isSelected()) {
                        data.setSize(c);
                        idata.setSize(c);
                        ydata = data.read();
                        double[] i0 = idata.read();
                        for (int i = 0; i < c; i++) {
                            ydata[i] = (i0[i] == 0.0) ? Double.NaN : ydata[i] / i0[i];
                        }
                    } else if (radioTFY.isSelected()) {
                        fdata.setSize(c);
                        idata.setSize(c);
                        ydata = fdata.read();
                        double[] i0 = idata.read();
                        for (int i = 0; i < c; i++) {
                            ydata[i] = (i0[i] == 0.0) ? Double.NaN : ydata[i] / i0[i];
                        }
                    }
                    if (ydata == null) {
                        scanSeries.clear();
                    } else {
                        edata.setSize(c);
                        double[] xdata = edata.read();
                        scanSeries.setData(xdata, ydata);
                    }
                }
            }
        } catch (Exception ex) {
            SwingUtils.showException(this, ex);
            ex.printStackTrace();
        }
    }

    void loadConfig() {
        DefaultComboBoxModel model = (DefaultComboBoxModel) comboSetup.getModel();
        model.removeAllElements();
        try {
            for (String line : Files.readAllLines(getConfigFile())) {
                if ((line != null) && (!line.trim().isEmpty())) {
                    String[] tokens = line.split("=");
                    if (tokens.length > 0) {
                        model.addElement(tokens[0].trim());
                    }
                }
            }
        } catch (Exception ex) {
        }
    }

    String expandPath(String path) {
        long time = System.currentTimeMillis();
        String mode;
        if (comboMode.getSelectedIndex() == 0) {
            mode = "plus";
        } else if (comboMode.getSelectedIndex() == 1) {
            mode = "minus";
        } else {
            mode = "lin_" + String.format("%1.0f", (Double) spinnerAlpha.getValue());
        }

        path = path.replaceAll("\\{date\\}", Chrono.getTimeStr(time, "YYYYMMdd"));
        path = path.replaceAll("\\{time\\}", Chrono.getTimeStr(time, "HHmmss"));
        path = path.replaceAll("\\{year\\}", Chrono.getTimeStr(time, "YYYY"));
        path = path.replaceAll("\\{month\\}", Chrono.getTimeStr(time, "MM"));
        path = path.replaceAll("\\{day\\}", Chrono.getTimeStr(time, "dd"));
        path = path.replaceAll("\\{el\\}", String.valueOf(comboSetup.getSelectedItem()));
        path = path.replaceAll("\\{mode\\}", mode);
        return path;
    }

    void setMode(Mode mode) {
        switch (mode) {
            case plus:
                comboMode.setSelectedIndex(0);
                spinnerOffset.setValue(offsets[0]);
                return;
            case minus:
                comboMode.setSelectedIndex(1);
                spinnerOffset.setValue(offsets[1]);
                return;
            case lh:
                comboMode.setSelectedIndex(2);
                spinnerOffset.setValue(offsets[2]);
                spinnerAlpha.setValue(0.0);
                return;
            case lv:
                comboMode.setSelectedIndex(2);
                spinnerOffset.setValue(offsets[3]);
                spinnerAlpha.setValue(90.0);
                return;
        }
    }

    boolean isManualRun() {
        return (comboRunType.getSelectedIndex() == 0);
    }

    void setElement() throws Exception {
        Properties prop = new Properties();
        prop.load(new FileInputStream(getConfigFile().toFile()));
        String selection = comboSetup.getSelectedItem().toString();
        String val = prop.getProperty(selection);
        String[] tokens = val.split(" ");
        if (tokens.length != 8) {
            throw new Exception("Invalid file format");
        }
        spinnerE1.setValue(Double.valueOf(tokens[0].trim()));
        spinnerE2.setValue(Double.valueOf(tokens[1].trim()));
        spinnerTime.setValue(Double.valueOf(tokens[2].trim()));
        spinnerDelay.setValue(Double.valueOf(tokens[3].trim()));

        offsets[0] = Double.valueOf(tokens[4].trim());
        offsets[1] = Double.valueOf(tokens[5].trim());
        offsets[2] = Double.valueOf(tokens[6].trim());
        offsets[3] = Double.valueOf(tokens[7].trim());
    }

    void setRunType() throws Exception {
        switch (comboRunType.getSelectedIndex()) {
            case 0: //Manual                    
                break;
            case 1: //+
                setMode(Mode.plus);
                break;
            case 2: //-
                setMode(Mode.minus);
                break;
            case 3: //LH
                setMode(Mode.lh);
                break;
            case 4: //LV
                setMode(Mode.lv);
                break;
            case 5: //+/-
                setMode(Mode.plus);
                break;
            case 6: //+/-/-/+
                setMode(Mode.plus);
                break;
            case 7: //LH/LV
                setMode(Mode.lh);
                break;
            case 8: //LH/LV/LV/LH      
                setMode(Mode.lh);
                break;
        }
        checkParameterControls();
    }

    void run() throws ContextStateException {
        HashMap args = new HashMap();
        Double e1 = (Double) spinnerE1.getValue();
        Double e2 = (Double) spinnerE2.getValue();
        args.put("E1", e1);
        args.put("E2", e2);
        args.put("TIME", (Double) spinnerTime.getValue());
        args.put("DELAY", (Double) spinnerDelay.getValue());
        args.put("MODE", comboMode.getSelectedItem().toString());
        args.put("OFFSET", (Double) spinnerOffset.getValue());
        args.put("ALPHA", (Double) spinnerAlpha.getValue());

        String file = expandPath(textFile.getText());
        args.put("FILE", file);

        String folder = expandPath(textFolder.getText());
        args.put("FOLDER", folder);
        scanStartTimestamp = System.currentTimeMillis();
        runAsync("EnergyScan", args);
        if (scanPlot != null) {
            scanPlot.getAxis(Plot.AxisId.X).setRange(Math.min(e1, e2), Math.max(e1, e2));
        }

    }

    void startPlot() throws Exception {
        PlotDescriptor descriptors = new PlotDescriptor("Energy Scan");
        ArrayList<LinePlot> plots = getContext().plot(new PlotDescriptor[]{descriptors}, null);
        scanPlot = (LinePlotBase) plots.get(0);
        scanSeries = scanPlot.getSeries(0);
    }

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

        buttonGroupPlot = new javax.swing.ButtonGroup();
        panelParameters = new javax.swing.JPanel();
        jLabel1 = new javax.swing.JLabel();
        spinnerE1 = new javax.swing.JSpinner();
        jLabel2 = new javax.swing.JLabel();
        spinnerE2 = new javax.swing.JSpinner();
        jLabel3 = new javax.swing.JLabel();
        spinnerTime = new javax.swing.JSpinner();
        jLabel4 = new javax.swing.JLabel();
        spinnerDelay = new javax.swing.JSpinner();
        jLabel5 = new javax.swing.JLabel();
        comboMode = new javax.swing.JComboBox();
        jLabel8 = new javax.swing.JLabel();
        spinnerOffset = new javax.swing.JSpinner();
        jLabel9 = new javax.swing.JLabel();
        spinnerAlpha = new javax.swing.JSpinner();
        jPanel1 = new javax.swing.JPanel();
        comboSetup = new javax.swing.JComboBox();
        buttonConfigure = new javax.swing.JButton();
        jLabel10 = new javax.swing.JLabel();
        jLabel11 = new javax.swing.JLabel();
        comboRunType = new javax.swing.JComboBox();
        jPanel2 = new javax.swing.JPanel();
        radioTEY = new javax.swing.JRadioButton();
        radioTFY = new javax.swing.JRadioButton();
        radioE = new javax.swing.JRadioButton();
        radioF = new javax.swing.JRadioButton();
        radioI0 = new javax.swing.JRadioButton();
        buttonPlot = new javax.swing.JButton();
        panelData = new javax.swing.JPanel();
        buttonDefaults = new javax.swing.JButton();
        jLabel6 = new javax.swing.JLabel();
        textFile = new javax.swing.JTextField();
        jLabel7 = new javax.swing.JLabel();
        textFolder = new javax.swing.JTextField();
        jPanel3 = new javax.swing.JPanel();
        buttonExecute = new javax.swing.JButton();
        buttonAbort = new javax.swing.JButton();

        panelParameters.setBorder(javax.swing.BorderFactory.createTitledBorder("Parameters"));

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

        spinnerE1.setModel(new javax.swing.SpinnerNumberModel(690.0d, 0.0d, 9999.0d, 1.0d));

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

        spinnerE2.setModel(new javax.swing.SpinnerNumberModel(755.0d, 0.0d, 9999.0d, 1.0d));

        jLabel3.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING);
        jLabel3.setText("Time(min):");

        spinnerTime.setModel(new javax.swing.SpinnerNumberModel(3.0d, 0.0d, 60.0d, 1.0d));

        jLabel4.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING);
        jLabel4.setText("Delay(s):");

        spinnerDelay.setModel(new javax.swing.SpinnerNumberModel(10.0d, 0.0d, 600.0d, 1.0d));

        jLabel5.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING);
        jLabel5.setText("Mode:");

        comboMode.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "CIRC +", "CIRC -", "LINEAR" }));
        comboMode.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                comboModeActionPerformed(evt);
            }
        });

        jLabel8.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING);
        jLabel8.setText("Offset:");

        spinnerOffset.setModel(new javax.swing.SpinnerNumberModel(0.0d, -20.0d, 20.0d, 1.0d));

        jLabel9.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING);
        jLabel9.setText("Alpha:");

        spinnerAlpha.setModel(new javax.swing.SpinnerNumberModel(0.0d, 0.0d, 90.0d, 1.0d));

        javax.swing.GroupLayout panelParametersLayout = new javax.swing.GroupLayout(panelParameters);
        panelParameters.setLayout(panelParametersLayout);
        panelParametersLayout.setHorizontalGroup(
            panelParametersLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(panelParametersLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(panelParametersLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jLabel5, javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(jLabel1, javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(jLabel3, javax.swing.GroupLayout.Alignment.TRAILING))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(panelParametersLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(spinnerE1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(spinnerTime, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(comboMode, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addGap(18, 18, Short.MAX_VALUE)
                .addGroup(panelParametersLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jLabel9, javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(jLabel8, javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(jLabel4, javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(jLabel2, javax.swing.GroupLayout.Alignment.TRAILING))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(panelParametersLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(spinnerE2, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(spinnerDelay, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(spinnerOffset, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(spinnerAlpha, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        panelParametersLayout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {comboMode, spinnerE1, spinnerTime});

        panelParametersLayout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {jLabel2, jLabel4, jLabel8, jLabel9});

        panelParametersLayout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {spinnerAlpha, spinnerDelay, spinnerE2, spinnerOffset});

        panelParametersLayout.setVerticalGroup(
            panelParametersLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(panelParametersLayout.createSequentialGroup()
                .addGap(0, 0, 0)
                .addGroup(panelParametersLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel1)
                    .addComponent(spinnerE1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel2)
                    .addComponent(spinnerE2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(panelParametersLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel3)
                    .addComponent(spinnerTime, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel4)
                    .addComponent(spinnerDelay, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(panelParametersLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel5)
                    .addComponent(comboMode, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel8)
                    .addComponent(spinnerOffset, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addGap(5, 5, 5)
                .addGroup(panelParametersLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(spinnerAlpha, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel9))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

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

        comboSetup.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                comboSetupActionPerformed(evt);
            }
        });

        buttonConfigure.setText("Configure");
        buttonConfigure.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                buttonConfigureActionPerformed(evt);
            }
        });

        jLabel10.setText("Element:");

        jLabel11.setText("Run Type:");

        comboRunType.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Manual", "+", "-", "LH", "LV", "+/-", "+/-/-/+", "LH/LV", "LH/LV/LV/LH" }));
        comboRunType.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                comboRunTypeActionPerformed(evt);
            }
        });

        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(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jLabel10, javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(jLabel11, javax.swing.GroupLayout.Alignment.TRAILING))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(comboSetup, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(buttonConfigure, javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(comboRunType, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        jPanel1Layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {buttonConfigure, comboRunType, comboSetup});

        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(comboSetup, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel10))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(buttonConfigure)
                .addGap(18, 18, 18)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel11)
                    .addComponent(comboRunType, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addContainerGap(15, Short.MAX_VALUE))
        );

        jPanel2.setBorder(javax.swing.BorderFactory.createTitledBorder("Plot Options"));

        buttonGroupPlot.add(radioTEY);
        radioTEY.setSelected(true);
        radioTEY.setText("TEY");
        radioTEY.setMinimumSize(new java.awt.Dimension(100, 22));
        radioTEY.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                radioPlotActionPerformed(evt);
            }
        });

        buttonGroupPlot.add(radioTFY);
        radioTFY.setText("TFY");
        radioTFY.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                radioPlotActionPerformed(evt);
            }
        });

        buttonGroupPlot.add(radioE);
        radioE.setText("TEY raw");
        radioE.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                radioPlotActionPerformed(evt);
            }
        });

        buttonGroupPlot.add(radioF);
        radioF.setText("TFY raw");
        radioF.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                radioPlotActionPerformed(evt);
            }
        });

        buttonGroupPlot.add(radioI0);
        radioI0.setText("I0");
        radioI0.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                radioPlotActionPerformed(evt);
            }
        });

        buttonPlot.setText("Plot");
        buttonPlot.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                buttonPlotActionPerformed(evt);
            }
        });

        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(radioTEY, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(radioTFY)
                    .addComponent(radioE)
                    .addComponent(radioF)
                    .addComponent(radioI0)
                    .addComponent(buttonPlot))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        jPanel2Layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {buttonPlot, radioE, radioF, radioI0, radioTEY, radioTFY});

        jPanel2Layout.setVerticalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel2Layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(radioTEY, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(radioTFY)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(radioE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(radioF)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(radioI0)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addComponent(buttonPlot)
                .addContainerGap())
        );

        panelData.setBorder(javax.swing.BorderFactory.createTitledBorder("Data"));

        buttonDefaults.setText("Defaults");
        buttonDefaults.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                buttonDefaultsActionPerformed(evt);
            }
        });

        jLabel6.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING);
        jLabel6.setText("File:");

        jLabel7.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING);
        jLabel7.setText("Folder:");

        javax.swing.GroupLayout panelDataLayout = new javax.swing.GroupLayout(panelData);
        panelData.setLayout(panelDataLayout);
        panelDataLayout.setHorizontalGroup(
            panelDataLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(panelDataLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(panelDataLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(panelDataLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                        .addComponent(jLabel7, javax.swing.GroupLayout.Alignment.TRAILING)
                        .addComponent(jLabel6, javax.swing.GroupLayout.Alignment.TRAILING))
                    .addGroup(panelDataLayout.createSequentialGroup()
                        .addGap(55, 55, 55)
                        .addGroup(panelDataLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(textFolder)
                            .addComponent(textFile))))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(buttonDefaults)
                .addContainerGap())
        );

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

        panelDataLayout.setVerticalGroup(
            panelDataLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(panelDataLayout.createSequentialGroup()
                .addGroup(panelDataLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel6)
                    .addComponent(textFile, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(panelDataLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel7)
                    .addComponent(textFolder, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(buttonDefaults, javax.swing.GroupLayout.PREFERRED_SIZE, 27, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addContainerGap())
        );

        jPanel3.setBorder(javax.swing.BorderFactory.createTitledBorder("Scan Control"));

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

        buttonAbort.setText("Abort");
        buttonAbort.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                buttonAbortActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3);
        jPanel3.setLayout(jPanel3Layout);
        jPanel3Layout.setHorizontalGroup(
            jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel3Layout.createSequentialGroup()
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(buttonAbort, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(buttonExecute, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
        jPanel3Layout.setVerticalGroup(
            jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel3Layout.createSequentialGroup()
                .addGap(4, 4, 4)
                .addComponent(buttonExecute)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(buttonAbort)
                .addContainerGap())
        );

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            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.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(jPanel3, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
                    .addComponent(panelData, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(panelParameters, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGap(16, 16, 16)
                .addComponent(panelParameters, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(panelData, 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()
                        .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jPanel3, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                    .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addContainerGap())
        );
    }// </editor-fold>//GEN-END:initComponents

    private void buttonExecuteActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonExecuteActionPerformed
        try {
            startPlot();
            batchIndex = 0;
            switch (comboRunType.getSelectedIndex()) {
                case 5:
                    batch = new Mode[]{Mode.plus, Mode.minus};
                    break;
                case 6:
                    batch = new Mode[]{Mode.plus, Mode.minus, Mode.minus, Mode.plus};
                    break;
                case 7:
                    batch = new Mode[]{Mode.lh, Mode.lv};
                    break;
                case 8:
                    batch = new Mode[]{Mode.lh, Mode.lv, Mode.lv, Mode.lh};
                    break;
                default:
                    batch = null;
            }
            run();
        } catch (Exception ex) {
            SwingUtils.showException(this, ex);
        }
    }//GEN-LAST:event_buttonExecuteActionPerformed

    private void buttonAbortActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonAbortActionPerformed
        batch = null;
        abort();
    }//GEN-LAST:event_buttonAbortActionPerformed

    private void comboSetupActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_comboSetupActionPerformed
        try {
            setElement();
            if (!isManualRun()) {
                setRunType();
            }
        } catch (Exception ex) {
            SwingUtils.showException(this, ex);
        }
    }//GEN-LAST:event_comboSetupActionPerformed

    EditorDialog dlgConfig;
    private void buttonConfigureActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonConfigureActionPerformed
        try {
            //Desktop.getDesktop().open(getConfigFile().toFile());
            if ((dlgConfig==null) || (!dlgConfig.isShowing())){
                String[] columns = new String[]{"Element", "E1", "E2", "Time", "Delay", "OffPlus", "OffMinus", "OffLH", "OffLV"};
                Class[] types = new Class[]{String.class, Double.class, Double.class, Double.class, Double.class, Double.class, Double.class, Double.class, Double.class};
                DsvEditor editor = new DsvEditor(columns , types, " ");
                dlgConfig = editor.getDialog(getView(),false);
                editor.load(getConfigFile().toString());
                editor.setTitle("Energy Scan Configuration");
            }
           dlgConfig.setSize(640, 320);
           showWindow(dlgConfig);
        } catch (Exception ex) {
            SwingUtils.showException(this, ex);
        }
    }//GEN-LAST:event_buttonConfigureActionPerformed

    private void comboModeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_comboModeActionPerformed
        checkParameterControls();
    }//GEN-LAST:event_comboModeActionPerformed

    private void radioPlotActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_radioPlotActionPerformed
        plot();
    }//GEN-LAST:event_radioPlotActionPerformed

    private void comboRunTypeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_comboRunTypeActionPerformed
        try {
            if (!isManualRun()) {
                setElement();
            }
            setRunType();
        } catch (Exception ex) {
            SwingUtils.showException(this, ex);
        }
    }//GEN-LAST:event_comboRunTypeActionPerformed

    private void buttonDefaultsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonDefaultsActionPerformed
        textFile.setText("{el}_{mode}");
        textFolder.setText("{year}_{month}/{date}");
    }//GEN-LAST:event_buttonDefaultsActionPerformed

    private void buttonPlotActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonPlotActionPerformed
        try {
            startPlot();
            plot();
        } catch (Exception ex) {
            SwingUtils.showException(this, ex);
        }

    }//GEN-LAST:event_buttonPlotActionPerformed

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton buttonAbort;
    private javax.swing.JButton buttonConfigure;
    private javax.swing.JButton buttonDefaults;
    private javax.swing.JButton buttonExecute;
    private javax.swing.ButtonGroup buttonGroupPlot;
    private javax.swing.JButton buttonPlot;
    private javax.swing.JComboBox comboMode;
    private javax.swing.JComboBox comboRunType;
    private javax.swing.JComboBox comboSetup;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel10;
    private javax.swing.JLabel jLabel11;
    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.JLabel jLabel8;
    private javax.swing.JLabel jLabel9;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JPanel jPanel3;
    private javax.swing.JPanel panelData;
    private javax.swing.JPanel panelParameters;
    private javax.swing.JRadioButton radioE;
    private javax.swing.JRadioButton radioF;
    private javax.swing.JRadioButton radioI0;
    private javax.swing.JRadioButton radioTEY;
    private javax.swing.JRadioButton radioTFY;
    private javax.swing.JSpinner spinnerAlpha;
    private javax.swing.JSpinner spinnerDelay;
    private javax.swing.JSpinner spinnerE1;
    private javax.swing.JSpinner spinnerE2;
    private javax.swing.JSpinner spinnerOffset;
    private javax.swing.JSpinner spinnerTime;
    private javax.swing.JTextField textFile;
    private javax.swing.JTextField textFolder;
    // End of variables declaration//GEN-END:variables
}
