package turgen.wizard;

import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Insets;
import java.awt.Rectangle;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Iterator;
import javax.swing.AbstractListModel;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.ListCellRenderer;
import javax.swing.ListModel;
import javax.swing.SwingUtilities;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import turgen.DialogManager;
import turgen.Turgen;
import turgen.UIPersistor;
import turgen.Utils;
import turgen.dtb.DOS2Binary;
import turgen.dtb.DOS2BinaryException;
import turgen.dtb.StatisticsDialog;
import turgen.generator.PulseCrate;
import turgen.plugin.BinaryConvertor;
import turgen.plugin.Plugin;

public class WizardDialog extends javax.swing.JDialog implements ListSelectionListener,UIPersistor {


    /** Creates new form WizardFrame */
    public WizardDialog() {
        setModal(true);
        initComponents();
        jlMethods.getSelectionModel().addListSelectionListener(this);
    }


    /** 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() {
        java.awt.GridBagConstraints gridBagConstraints;

        rbg1 = new javax.swing.ButtonGroup();
        fcBinaryFile = new javax.swing.JFileChooser();
        fcOutputFile = new javax.swing.JFileChooser();
        pButtonControls = new javax.swing.JPanel();
        btnBack = new javax.swing.JButton();
        btnNext = new javax.swing.JButton();
        btnFinish = new javax.swing.JButton();
        btnCancel = new javax.swing.JButton();
        pMainArea = new javax.swing.JPanel();
        pCards = new javax.swing.JPanel();
        pSetup = new javax.swing.JPanel();
        pInputFile = new javax.swing.JPanel();
        jlbFile = new javax.swing.JLabel();
        jtfInputFile = new javax.swing.JTextField();
        btnBrowse = new javax.swing.JButton();
        pModif = new javax.swing.JPanel();
        jrbTurbo2000 = new javax.swing.JRadioButton();
        jrbSuperTurbo = new javax.swing.JRadioButton();
        jrbKSOTurbo2000 = new javax.swing.JRadioButton();
        jrbTurbo2000F = new javax.swing.JRadioButton();
        jrbTurboBlizzard = new javax.swing.JRadioButton();
        jlbCs = new javax.swing.JLabel();
        jlbPl = new javax.swing.JLabel();
        jrbTurboROM = new javax.swing.JRadioButton();
        jlbPl1 = new javax.swing.JLabel();
        jrbAST = new javax.swing.JRadioButton();
        jlbFill1 = new javax.swing.JLabel();
        jrbHardTurbo = new javax.swing.JRadioButton();
        jrbStandard = new javax.swing.JRadioButton();
        jlbPl2 = new javax.swing.JLabel();
        jrbLowerSilesia = new javax.swing.JRadioButton();
        jlbPl3 = new javax.swing.JLabel();
        pHelp = new javax.swing.JPanel();
        jScrollPane1 = new javax.swing.JScrollPane();
        jPanel1 = new javax.swing.JPanel();
        jLabel7 = new javax.swing.JLabel();
        pExtraOpts = new javax.swing.JPanel();
        jcbLoadersOnly = new javax.swing.JCheckBox();
        pSorryNoBianry = new javax.swing.JPanel();
        jLabel2 = new javax.swing.JLabel();
        jlbBinaryError = new javax.swing.JLabel();
        pCreateItem = new javax.swing.JPanel();
        pOutput = new javax.swing.JPanel();
        pOutputFile = new javax.swing.JPanel();
        jLabel5 = new javax.swing.JLabel();
        jtfOutputFile = new javax.swing.JTextField();
        jtfBrowseOutput = new javax.swing.JButton();
        pPulses = new javax.swing.JPanel();
        jLabel6 = new javax.swing.JLabel();
        jcoPulses = new javax.swing.JComboBox();
        pMethods = new javax.swing.JPanel();
        jspMethods = new javax.swing.JScrollPane();
        jlMethods = new javax.swing.JList();
        pSorryNoMethod = new javax.swing.JPanel();
        jTextPane1 = new javax.swing.JTextPane();

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        setTitle("Wizard for binary files");
        getContentPane().setLayout(new java.awt.BorderLayout(8, 4));

        pButtonControls.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.RIGHT));

        btnBack.setMnemonic('b');
        btnBack.setText("<< Back");
        btnBack.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                onBack(evt);
            }
        });
        pButtonControls.add(btnBack);

        btnNext.setMnemonic('n');
        btnNext.setText("Next >>");
        btnNext.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                onNext(evt);
            }
        });
        pButtonControls.add(btnNext);

        btnFinish.setMnemonic('f');
        btnFinish.setText("Finish");
        btnFinish.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                onFinish(evt);
            }
        });
        pButtonControls.add(btnFinish);

        btnCancel.setText("Cancel");
        btnCancel.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                onCancel(evt);
            }
        });
        pButtonControls.add(btnCancel);

        getContentPane().add(pButtonControls, java.awt.BorderLayout.SOUTH);

        pMainArea.setLayout(new java.awt.BorderLayout(0, 4));

        pCards.setLayout(new java.awt.CardLayout());

        pSetup.setBorder(javax.swing.BorderFactory.createEtchedBorder());
        pSetup.setLayout(new java.awt.GridBagLayout());

        pInputFile.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder(), "Input binary file"));
        pInputFile.setLayout(new java.awt.GridBagLayout());

        jlbFile.setForeground(new java.awt.Color(0, 0, 255));
        jlbFile.setText("File:");
        jlbFile.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                onFileLabelClicked(evt);
            }
            public void mouseEntered(java.awt.event.MouseEvent evt) {
                jlbFileMouseEntered(evt);
            }
            public void mouseExited(java.awt.event.MouseEvent evt) {
                jlbFileMouseExited(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        pInputFile.add(jlbFile, gridBagConstraints);

        jtfInputFile.setColumns(30);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(0, 3, 0, 3);
        pInputFile.add(jtfInputFile, gridBagConstraints);

        btnBrowse.setMnemonic('b');
        btnBrowse.setText("Browse");
        btnBrowse.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                onBrowseInputBinary(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
        pInputFile.add(btnBrowse, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH;
        gridBagConstraints.weightx = 1.0;
        pSetup.add(pInputFile, gridBagConstraints);

        pModif.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder(), "Data recorder modification"));
        pModif.setLayout(new java.awt.GridBagLayout());

        rbg1.add(jrbTurbo2000);
        jrbTurbo2000.setSelected(true);
        jrbTurbo2000.setText("Turbo 2000");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(0, 4, 0, 0);
        pModif.add(jrbTurbo2000, gridBagConstraints);

        rbg1.add(jrbSuperTurbo);
        jrbSuperTurbo.setText("Super turbo");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(0, 4, 0, 0);
        pModif.add(jrbSuperTurbo, gridBagConstraints);

        rbg1.add(jrbKSOTurbo2000);
        jrbKSOTurbo2000.setText("KSO Turbo 2000");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(0, 4, 0, 0);
        pModif.add(jrbKSOTurbo2000, gridBagConstraints);

        rbg1.add(jrbTurbo2000F);
        jrbTurbo2000F.setText("Turbo 2000F");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(0, 4, 0, 0);
        pModif.add(jrbTurbo2000F, gridBagConstraints);

        rbg1.add(jrbTurboBlizzard);
        jrbTurboBlizzard.setText("Turbo Blizzard");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 3;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(0, 4, 0, 0);
        pModif.add(jrbTurboBlizzard, gridBagConstraints);

        jlbCs.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
        jlbCs.setIcon(new javax.swing.ImageIcon(getClass().getResource("/turgen/resources/flag_cs.png"))); // NOI18N
        jlbCs.setToolTipText("Czechoslovakia and Czech Republic");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        pModif.add(jlbCs, gridBagConstraints);

        jlbPl.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
        jlbPl.setIcon(new javax.swing.ImageIcon(getClass().getResource("/turgen/resources/flag_pl.png"))); // NOI18N
        jlbPl.setToolTipText("Poland");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        pModif.add(jlbPl, gridBagConstraints);

        rbg1.add(jrbTurboROM);
        jrbTurboROM.setText("Turbo ROM");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(0, 4, 0, 0);
        pModif.add(jrbTurboROM, gridBagConstraints);

        jlbPl1.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
        jlbPl1.setIcon(new javax.swing.ImageIcon(getClass().getResource("/turgen/resources/flag_pl.png"))); // NOI18N
        jlbPl1.setToolTipText("Poland");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        pModif.add(jlbPl1, gridBagConstraints);

        rbg1.add(jrbAST);
        jrbAST.setText("Atari Super Turbo");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(0, 4, 0, 0);
        pModif.add(jrbAST, gridBagConstraints);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 4;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.gridheight = 3;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
        gridBagConstraints.weightx = 1.0;
        pModif.add(jlbFill1, gridBagConstraints);

        rbg1.add(jrbHardTurbo);
        jrbHardTurbo.setText("Hard Turbo");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 3;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(0, 4, 0, 0);
        pModif.add(jrbHardTurbo, gridBagConstraints);

        rbg1.add(jrbStandard);
        jrbStandard.setText("Standard");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 4;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(0, 4, 0, 0);
        pModif.add(jrbStandard, gridBagConstraints);

        jlbPl2.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
        jlbPl2.setIcon(new javax.swing.ImageIcon(getClass().getResource("/turgen/resources/flag_un.png"))); // NOI18N
        jlbPl2.setToolTipText("Poland");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 4;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        pModif.add(jlbPl2, gridBagConstraints);

        rbg1.add(jrbLowerSilesia);
        jrbLowerSilesia.setText("Lower Silesia Turbo 2000");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 3;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(0, 4, 0, 0);
        pModif.add(jrbLowerSilesia, gridBagConstraints);

        jlbPl3.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
        jlbPl3.setIcon(new javax.swing.ImageIcon(getClass().getResource("/turgen/resources/flag_pl.png"))); // NOI18N
        jlbPl3.setToolTipText("Poland");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 3;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        pModif.add(jlbPl3, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH;
        gridBagConstraints.weightx = 1.0;
        pSetup.add(pModif, gridBagConstraints);

        pHelp.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder(), "Help"));
        pHelp.setLayout(new java.awt.BorderLayout());

        jScrollPane1.setBorder(null);
        jScrollPane1.setAlignmentX(0.0F);
        jScrollPane1.setAlignmentY(0.0F);

        jPanel1.setAlignmentX(0.0F);
        jPanel1.setAlignmentY(0.0F);
        jPanel1.setLayout(new java.awt.BorderLayout());

        jLabel7.setFont(new java.awt.Font("Dialog", 0, 12)); // NOI18N
        jLabel7.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
        jLabel7.setText("<html>\nUse this wizard to comfortably select best method for conversion of your binary file to turbo.<br><br>\n\n<b>1st step</b><br>\nIn the first step select the binary file you want to convert and your data recorder modification.<br>\n<br>\n<b>2nd step</b><br>\nSelect one of the conversion methods that will be offered to you.<br>\nOffered methods are sorted according to the number of pilot tones needed.\n</html>");
        jLabel7.setVerticalAlignment(javax.swing.SwingConstants.TOP);
        jLabel7.setHorizontalTextPosition(javax.swing.SwingConstants.LEFT);
        jPanel1.add(jLabel7, java.awt.BorderLayout.WEST);

        jScrollPane1.setViewportView(jPanel1);

        pHelp.add(jScrollPane1, java.awt.BorderLayout.CENTER);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 3;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        pSetup.add(pHelp, gridBagConstraints);

        pExtraOpts.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder(), "Advanced settings"));
        pExtraOpts.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT, 2, 0));

        jcbLoadersOnly.setMnemonic('a');
        jcbLoadersOnly.setSelected(true);
        jcbLoadersOnly.setText("Offer only methods that require available loaders (recommended)");
        pExtraOpts.add(jcbLoadersOnly);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH;
        gridBagConstraints.weightx = 1.0;
        pSetup.add(pExtraOpts, gridBagConstraints);

        pCards.add(pSetup, "crdSetup");

        pSorryNoBianry.setBorder(javax.swing.BorderFactory.createEtchedBorder());
        pSorryNoBianry.setLayout(new java.awt.GridBagLayout());

        jLabel2.setFont(new java.awt.Font("Dialog", 1, 18)); // NOI18N
        jLabel2.setForeground(javax.swing.UIManager.getDefaults().getColor("nb.errorForeground"));
        jLabel2.setText("<HTML>\nNOT A BINARY FILE <BR><BR>\nSelected file is not a binary file.\n\n</HTML>\n");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(4, 64, 0, 0);
        pSorryNoBianry.add(jLabel2, gridBagConstraints);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(4, 64, 0, 0);
        pSorryNoBianry.add(jlbBinaryError, gridBagConstraints);

        pCards.add(pSorryNoBianry, "crdNoBinary");

        pCreateItem.setBorder(javax.swing.BorderFactory.createEtchedBorder());
        pCreateItem.setLayout(new java.awt.BorderLayout(0, 4));

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

        pOutputFile.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder(), "Output file"));
        pOutputFile.setLayout(new java.awt.GridBagLayout());

        jLabel5.setForeground(java.awt.Color.blue);
        jLabel5.setText("File:");
        jLabel5.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                onOutputFileLabelClicked(evt);
            }
            public void mouseEntered(java.awt.event.MouseEvent evt) {
                onOutputFileLabelEntered(evt);
            }
            public void mouseExited(java.awt.event.MouseEvent evt) {
                onOutputFileMouseExited(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(0, 4, 0, 0);
        pOutputFile.add(jLabel5, gridBagConstraints);

        jtfOutputFile.setColumns(30);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(0, 3, 0, 3);
        pOutputFile.add(jtfOutputFile, gridBagConstraints);

        jtfBrowseOutput.setMnemonic('o');
        jtfBrowseOutput.setText("Browse");
        jtfBrowseOutput.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                onBrowseOutput(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
        pOutputFile.add(jtfBrowseOutput, gridBagConstraints);

        pOutput.add(pOutputFile, java.awt.BorderLayout.SOUTH);

        pPulses.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder(), "Available pulses"));
        pPulses.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT, 4, 5));

        jLabel6.setText("Pulses:");
        pPulses.add(jLabel6);

        pPulses.add(jcoPulses);

        pOutput.add(pPulses, java.awt.BorderLayout.CENTER);

        pCreateItem.add(pOutput, java.awt.BorderLayout.SOUTH);

        pMethods.setBorder(javax.swing.BorderFactory.createTitledBorder("Suitable conversion methods"));
        pMethods.setLayout(new java.awt.BorderLayout());

        jlMethods.setCellRenderer(new MethodListCellRenderer());
        jspMethods.setViewportView(jlMethods);

        pMethods.add(jspMethods, java.awt.BorderLayout.CENTER);

        pCreateItem.add(pMethods, java.awt.BorderLayout.CENTER);

        pCards.add(pCreateItem, "crdCreateItem");

        pSorryNoMethod.setBorder(javax.swing.BorderFactory.createEtchedBorder());
        pSorryNoMethod.setLayout(new java.awt.GridBagLayout());

        jTextPane1.setEditable(false);
        jTextPane1.setBackground(javax.swing.UIManager.getDefaults().getColor("windowBorder"));
        jTextPane1.setBorder(null);
        jTextPane1.setContentType("text/html"); // NOI18N
        jTextPane1.setText("<HTML>\n<B> NO SUITABLE CONVERSION METHOD FOUND<BR><BR>\nTURGEN SYSTEM is not able to find suitable method<BR>\n to convert this file.</B><BR><BR>\nThis usually means that the input file overlaps with small binary<BR>\n loaders shipped with TURGEN SYSTEM.<BR>\nTo solve this situation, try to obtain the same program in a diferently<BR>\nstructured binary file.\n</HTML>\n");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(8, 8, 8, 8);
        pSorryNoMethod.add(jTextPane1, gridBagConstraints);

        pCards.add(pSorryNoMethod, "crdNoMethod");

        pMainArea.add(pCards, java.awt.BorderLayout.CENTER);

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

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void onBrowseInputBinary(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_onBrowseInputBinary

        /*Browsed nothing*/
        if (fcBinaryFile.showOpenDialog(this)!=JFileChooser.APPROVE_OPTION) return;

        /*Push the file name into the textfield*/
        jtfInputFile.setText(fcBinaryFile.getSelectedFile().getAbsolutePath());
    }//GEN-LAST:event_onBrowseInputBinary

    private void onBack(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_onBack
         setButtonsEnabled(false,true,false,true);
         CardLayout c =(CardLayout)pCards.getLayout();
         c.show(pCards, "crdSetup");
    }//GEN-LAST:event_onBack

    private void onNext(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_onNext

        /*Check whether file exists*/
        File f = new File(jtfInputFile.getText());
        
        String msg = Utils.checkIfHeaderCanBeSet(f,false);
        if (msg!=null) {
            JOptionPane.showMessageDialog(null, msg,"Input binary file",JOptionPane.ERROR_MESSAGE);
            return;
        }

        /*Check whether the file is binary*/
        DOS2Binary dtb = new DOS2Binary(jtfInputFile.getText());
        try {
            dtb.analyzeFromFile();
        }
        catch (DOS2BinaryException d2be) {
            d2be.printStackTrace();
            jlbBinaryError.setText(d2be.getFormattedMessage());
            showNoBinary();
            return;
        }
        catch (IOException ioe) {
            ioe.printStackTrace();
            jlbBinaryError.setText(ioe.toString());
            showNoBinary();
            return;
        }

       

        /*Handle turbo modification*/
        int modType=getModificationType();
        

        /*Create model if possible*/
        MethodListModel model = createModel(dtb,modType,jcbLoadersOnly.isSelected());
        if (model==null) {
            showNoSuchMethod();
            return;
        }

        /*Set the model and proceed to the next page*/
        showMethodList(model);

    }//GEN-LAST:event_onNext

    private void onFinish(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_onFinish
       /*Check whether some method is selected*/
       int cc = jlMethods.getSelectedIndex();
       
       /*If not. emit the warning message*/
       if (cc==-1) {
           JOptionPane.showMessageDialog(this, "No conversion method selected. Please select one.");
           return;
       }
       
       BinaryConvertor bc = ((MethodEntry)jlMethods.getSelectedValue()).convertor;
       

       /*Check whether some pulses are selected*/
       int pc = jcoPulses.getSelectedIndex();
       if (bc.requiresPulses()==true && pc==-1) {
           JOptionPane.showMessageDialog(this, "No pulses selected. Please select some pulses.");
           return;
       }

       /*Creating playlist item*/
       MethodListModel mtm = (MethodListModel)jlMethods.getModel();
       Turgen.playList.addItem(mtm.methodEntries[cc].convertor.getPlaylistItem(mtm.dtb, mtm.inputFile,jtfOutputFile.getText() , (PulseCrate)jcoPulses.getSelectedItem()));

       setVisible(false);
       dispose();

    }//GEN-LAST:event_onFinish

    private void onCancel(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_onCancel
        setVisible(false);
        dispose();
    }//GEN-LAST:event_onCancel

    private void onBrowseOutput(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_onBrowseOutput

        /*Browsed nothing*/
        if (fcOutputFile.showSaveDialog(this)!=JFileChooser.APPROVE_OPTION) return;

        /*Push the file name into the textfield*/
        jtfOutputFile.setText(fcOutputFile.getSelectedFile().getAbsolutePath());
    }//GEN-LAST:event_onBrowseOutput

    private void onFileLabelClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_onFileLabelClicked
            if (evt.getClickCount()==1) {
                showStatistics();
            }
    }//GEN-LAST:event_onFileLabelClicked

    private void jlbFileMouseEntered(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jlbFileMouseEntered
        ((JLabel)(evt.getSource())).setForeground(Color.red);
    }//GEN-LAST:event_jlbFileMouseEntered

    private void jlbFileMouseExited(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jlbFileMouseExited
        ((JLabel)(evt.getSource())).setForeground(Color.blue);
    }//GEN-LAST:event_jlbFileMouseExited

    private void onOutputFileLabelEntered(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_onOutputFileLabelEntered
        //jlbFileMouseEntered(evt);
    }//GEN-LAST:event_onOutputFileLabelEntered

    private void onOutputFileMouseExited(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_onOutputFileMouseExited
        //jlbFileMouseExited(evt);
    }//GEN-LAST:event_onOutputFileMouseExited

    private void onOutputFileLabelClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_onOutputFileLabelClicked
            
    }//GEN-LAST:event_onOutputFileLabelClicked

    /**
    * @param args the command line arguments
    */
    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new WizardDialog().setVisible(true);
            }
        });
    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton btnBack;
    private javax.swing.JButton btnBrowse;
    private javax.swing.JButton btnCancel;
    private javax.swing.JButton btnFinish;
    private javax.swing.JButton btnNext;
    private javax.swing.JFileChooser fcBinaryFile;
    private javax.swing.JFileChooser fcOutputFile;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel5;
    private javax.swing.JLabel jLabel6;
    private javax.swing.JLabel jLabel7;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JTextPane jTextPane1;
    private javax.swing.JCheckBox jcbLoadersOnly;
    private javax.swing.JComboBox jcoPulses;
    private javax.swing.JList jlMethods;
    private javax.swing.JLabel jlbBinaryError;
    private javax.swing.JLabel jlbCs;
    private javax.swing.JLabel jlbFile;
    private javax.swing.JLabel jlbFill1;
    private javax.swing.JLabel jlbPl;
    private javax.swing.JLabel jlbPl1;
    private javax.swing.JLabel jlbPl2;
    private javax.swing.JLabel jlbPl3;
    private javax.swing.JRadioButton jrbAST;
    private javax.swing.JRadioButton jrbHardTurbo;
    private javax.swing.JRadioButton jrbKSOTurbo2000;
    private javax.swing.JRadioButton jrbLowerSilesia;
    private javax.swing.JRadioButton jrbStandard;
    private javax.swing.JRadioButton jrbSuperTurbo;
    private javax.swing.JRadioButton jrbTurbo2000;
    private javax.swing.JRadioButton jrbTurbo2000F;
    private javax.swing.JRadioButton jrbTurboBlizzard;
    private javax.swing.JRadioButton jrbTurboROM;
    private javax.swing.JScrollPane jspMethods;
    private javax.swing.JButton jtfBrowseOutput;
    private javax.swing.JTextField jtfInputFile;
    private javax.swing.JTextField jtfOutputFile;
    private javax.swing.JPanel pButtonControls;
    private javax.swing.JPanel pCards;
    private javax.swing.JPanel pCreateItem;
    private javax.swing.JPanel pExtraOpts;
    private javax.swing.JPanel pHelp;
    private javax.swing.JPanel pInputFile;
    private javax.swing.JPanel pMainArea;
    private javax.swing.JPanel pMethods;
    private javax.swing.JPanel pModif;
    private javax.swing.JPanel pOutput;
    private javax.swing.JPanel pOutputFile;
    private javax.swing.JPanel pPulses;
    private javax.swing.JPanel pSetup;
    private javax.swing.JPanel pSorryNoBianry;
    private javax.swing.JPanel pSorryNoMethod;
    private javax.swing.ButtonGroup rbg1;
    // End of variables declaration//GEN-END:variables


    public void updateFileDialogUI() {
        SwingUtilities.updateComponentTreeUI(fcBinaryFile);
        SwingUtilities.updateComponentTreeUI(fcOutputFile);
    }

    
    public void setButtonsEnabled(boolean bBack,boolean bNext,boolean bFinish,boolean bCancel) {
        btnBack.setEnabled(bBack);
        btnNext.setEnabled(bNext);
        btnFinish.setEnabled(bFinish);
        btnCancel.setEnabled(bCancel);
    }
    

    private void reset() {
        jtfInputFile.setText("");
        jtfOutputFile.setText("");
        CardLayout c =(CardLayout)pCards.getLayout();
        c.show(pCards, "crdSetup");
        setButtonsEnabled(false,true,false,true);
    }

    private void showNoSuchMethod() {
        CardLayout c =(CardLayout)pCards.getLayout();
        c.show(pCards, "crdNoMethod");
        setButtonsEnabled(true,false,false,true);

    }

    private void showNoBinary() {
        CardLayout c =(CardLayout)pCards.getLayout();
        c.show(pCards, "crdNoBinary");
        setButtonsEnabled(true,false,false,true);
    }

    public void startWizard() {
        reset();
        setVisible(true);
    }
    
    private boolean checkExistence() {
        File f = new File (jtfInputFile.getText());
        if (!f.exists()) return false; else return true;

    }

    private DOS2Binary checkBinary() {
        try {
            DOS2Binary dtb = new DOS2Binary(jtfInputFile.getText());
            dtb.analyzeFromFile();
            return dtb;
        }
        catch (DOS2BinaryException dtbe) {
            return null;
        }
        catch (Exception e) {
            return null;
        }
    }

    private MethodListModel createModel(DOS2Binary dtb, int modType, boolean loadersOnly) {
        
        /*Obtain all plugins and put them into arrayList*/
        ArrayList plugins = new ArrayList();
        ArrayList binConvs = new ArrayList();
        ArrayList acceptedConvs = new ArrayList();

        Plugin[] pgns = Turgen.pluginManager.getPlugins();
        for(int i=0;i<pgns.length;i++) {
            plugins.add(pgns[i]);
        }
        

        Plugin p;
        int l = plugins.size();

        for(int i=0;i<l;i++) {
            p = (Plugin)plugins.get(i);
            BinaryConvertor[] bcs = p.getBinaryConvertors();
            if (bcs==null) continue;
            for (int k=0;k<bcs.length;k++) {
                binConvs.add(bcs[k]);
            }
        }

        Iterator it;
        it = binConvs.iterator();

        /*Filter acceptable methods*/
        while(it.hasNext()) {
            BinaryConvertor bc = (BinaryConvertor)it.next();

            /*Binary file and recorder modification*/
            if (bc.acceptsBinary(dtb) && bc.acceptsRecorderModification(modType)) {

                /*Loader availability*/
                if (loadersOnly==false || (loadersOnly==true && bc.hasLoader()==true)) {
                    acceptedConvs.add(bc);
                }
            }
        }

        /*No acceptable convertor - bailing out*/
        if (acceptedConvs.isEmpty()==true) return null;

        /*Time to create the model*/
        MethodListModel model = new MethodListModel(acceptedConvs,jtfInputFile.getText(),dtb,modType);

        return model;

    }

    private void showMethodList(ListModel model) {
         CardLayout c =(CardLayout)pCards.getLayout();
         c.show(pCards, "crdCreateItem");
         setButtonsEnabled(true,false,true,true);
         jlMethods.setModel(model);
         jlMethods.getSelectionModel().setSelectionInterval(0,0);
    }

    public void valueChanged(ListSelectionEvent e) {

        int cc = jlMethods.getSelectedIndex();
        if (cc==-1) {
            jcoPulses.removeAllItems();
        }
        
        else {
          MethodListModel mtm = (MethodListModel)jlMethods.getModel();
          MethodEntry me = mtm.methodEntries[cc];

          jcoPulses.removeAllItems();

          for(int i=0;i<me.pulseArray.length;i++) {
              jcoPulses.addItem(me.pulseArray[i]);
          }
          
        }

    }

    private int getModificationType() {

        if (jrbTurbo2000.isSelected()==true) return BinaryConvertor.REC_MOD_CS_T2000;
        if (jrbSuperTurbo.isSelected()==true) return BinaryConvertor.REC_MOD_CS_ST;
        if (jrbKSOTurbo2000.isSelected()==true) return BinaryConvertor.REC_MOD_PL_KSOT2000;
        if (jrbTurbo2000F.isSelected()==true) return BinaryConvertor.REC_MOD_PL_T2000F;
        if (jrbTurboBlizzard.isSelected()==true) return BinaryConvertor.REC_MOD_PL_BLIZZARD;
        if (jrbTurboROM.isSelected()==true) return BinaryConvertor.REC_MOD_PL_TURBO_ROM;
        if (jrbAST.isSelected()==true) return BinaryConvertor.REC_MOD_PL_AST;
        if (jrbHardTurbo.isSelected()==true) return BinaryConvertor.REC_MOD_PL_HARD_TURBO;
        if (jrbLowerSilesia.isSelected()==true) return BinaryConvertor.REC_MOD_PL_LOWER_SILESIA_2000;
        if (jrbStandard.isSelected()==true) return BinaryConvertor.REC_MOD_UN_STANDARD;
        

        return -1;
    }

    private void setModificationType(int modif) {

        switch (modif) {
            case BinaryConvertor.REC_MOD_CS_T2000: {jrbTurbo2000.setSelected(true);break;}
            case BinaryConvertor.REC_MOD_CS_ST: {jrbSuperTurbo.setSelected(true);break;}
            case BinaryConvertor.REC_MOD_PL_KSOT2000: {jrbKSOTurbo2000.setSelected(true);break;}
            case BinaryConvertor.REC_MOD_PL_T2000F: {jrbTurbo2000F.setSelected(true);break;}
            case BinaryConvertor.REC_MOD_PL_BLIZZARD: {jrbTurboBlizzard.setSelected(true);break;}
            case BinaryConvertor.REC_MOD_PL_TURBO_ROM: {jrbTurboROM.setSelected(true);break;}
            case BinaryConvertor.REC_MOD_PL_AST: {jrbAST.setSelected(true);break;}
            case BinaryConvertor.REC_MOD_PL_HARD_TURBO: {jrbHardTurbo.setSelected(true);break;}    
            case BinaryConvertor.REC_MOD_PL_LOWER_SILESIA_2000: {jrbLowerSilesia.setSelected(true);break;}    
            case BinaryConvertor.REC_MOD_UN_STANDARD: {jrbStandard.setSelected(true);break;}    
        }
    }


    public Object[] getPersistenceData() {

        Object pData[] = new Object[5];

        /*Bounds and data recorder modification*/
        pData[0]=getBounds();
        pData[1]=new Integer(getModificationType());

        /*File chooser directories*/
        pData[2]=fcBinaryFile.getCurrentDirectory().getAbsolutePath();
        pData[3]=fcOutputFile.getCurrentDirectory().getAbsolutePath();
        pData[4]=Boolean.valueOf(jcbLoadersOnly.isSelected());

        return pData;


    }

    public void setPersistenceData(Object[] data) throws Exception {

        /*Bounds and data recorder modification*/
        setBounds((Rectangle)data[0]);
        setModificationType(((Integer)data[1]).intValue());

        /*File chooser directories*/
        fcBinaryFile.setCurrentDirectory(new File((String)data[2]));
        fcOutputFile.setCurrentDirectory(new File((String)data[3]));

        jcbLoadersOnly.setSelected(((Boolean)data[4]).booleanValue());
    }

    public String getPersistenceId() {
        return getClass().getName();
    }

    public void setPersistenceDefaults() {
        pack();
        DialogManager.centerContainer(this);    
    }
    
    private void showStatistics() {
        
        String fn =jtfInputFile.getText().trim();

        if (StatisticsDialog.fillStatisticsDialog(fn, Turgen.dlm.dlgStatistics)==true) {
            Turgen.dlm.dlgStatistics.setVisible(true);
        }
    }

    


    /** Entry for conversion method*/
    private static class MethodEntry {

        MethodEntry(int pTones,String cpt,PulseCrate[] pulses,BinaryConvertor bc) {
            pilotTones=pTones;
            caption=cpt;
            pulseArray=pulses;
            convertor=bc;
        }

        int pilotTones;
        String caption;
        PulseCrate[] pulseArray;
        BinaryConvertor convertor;

    }

    private static class MethodListModel extends AbstractListModel {

        private MethodEntry[] methodEntries;

        
        private int methodCount;
        String inputFile;
        DOS2Binary dtb;


        MethodListModel(ArrayList convs,String inputFile,DOS2Binary dtb,int recMod) {

            this.inputFile=inputFile;
            int l = convs.size();

            methodEntries = new MethodEntry[l];
            methodCount=l;
            this.dtb=dtb;
           
            
            Iterator it = convs.iterator();
            int i=0;
            while(it.hasNext()) {
                BinaryConvertor bc = (BinaryConvertor)it.next();
                methodEntries[i]=new MethodEntry(bc.getPilotToneCount(dtb),bc.getDescription(),bc.getSpeeds(recMod),bc);
                i++;
            }

            Arrays.sort(methodEntries, new Comparator() {
                public int compare(Object o1,Object o2) {
                    
                    MethodEntry e1 = (MethodEntry)o1;
                    MethodEntry e2 = (MethodEntry)o2;
                    
                    if (e1.pilotTones<e2.pilotTones) return -1;
                    if (e1.pilotTones>e2.pilotTones) return +1;
                    
                    /*Equality - super turbo support is preferred*/
                    boolean b1 = e1.convertor.exhaustsRecorderModification(BinaryConvertor.REC_MOD_CS_ST);
                    boolean b2 = e2.convertor.exhaustsRecorderModification(BinaryConvertor.REC_MOD_CS_ST);


                    if (b1==true && b2==false) return -1;
                    if (b1==false && b2==true) return +1;

                    return 0;

                }

            });

        }

        

        public Object getElementAt(int index) {
            return methodEntries[index];
        }

        public int getSize() {
            return methodCount;
        }


    }
   
    private static class MethodListCellRenderer extends JPanel implements ListCellRenderer {

        private JLabel lName;
        private JLabel lTones;
        private Insets insets = new Insets(4,2,4,4);

        MethodListCellRenderer() {

            super();
            setLayout(new BorderLayout(2,2));

            lName= new JLabel();
            lTones= new JLabel();

            add("Center",lName);
            add("East",lTones);

            lTones.setHorizontalAlignment(JLabel.RIGHT);
            lName.setHorizontalAlignment(JLabel.LEFT);

        }

        public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {


            MethodEntry me = (MethodEntry)(list.getModel().getElementAt(index));

            lName.setText(me.caption);
            lTones.setText(Integer.toString(me.pilotTones));

            if (isSelected==true) {
                setBackground(list.getSelectionBackground());
                setForeground(list.getSelectionForeground());
                lName.setBackground(list.getSelectionBackground());
                lName.setForeground(list.getSelectionForeground());
                lTones.setBackground(list.getSelectionBackground());
                lTones.setForeground(list.getSelectionForeground());

            }
            else {
                setBackground(list.getBackground());
                setForeground(list.getForeground());
                lName.setBackground(list.getBackground());
                lName.setForeground(list.getForeground());
                lTones.setBackground(list.getBackground());
                lTones.setForeground(list.getForeground());
            }

            return this;
        }

        public Insets getInsets() {
            return insets;
        }

    }

}
