package turgen.plugin.btape;

import java.awt.event.ItemEvent;
import java.io.File;
import turgen.plugin.*;
import java.util.StringTokenizer;
import javax.swing.*;
import turgen.Utils;

public class BTapePluginPanel extends javax.swing.JPanel {


    public InOutProvider ioProvider;

    /** Creates new form BTapePluginsPanel */
    public BTapePluginPanel() {
        initComponents();
    }
    
    /** 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;

        jLabel3 = new javax.swing.JLabel();
        pHeader = new javax.swing.JPanel();
        jlbName = new javax.swing.JLabel();
        jtfName = new javax.swing.JTextField();
        jLabel1 = new javax.swing.JLabel();
        jcoMode = new javax.swing.JComboBox();
        btnGuessHeader = new javax.swing.JButton();
        pBinaryFile = new javax.swing.JPanel();
        jlbPauses = new javax.swing.JLabel();
        jtfPauses = new javax.swing.JTextField();
        jcoBinLoad = new javax.swing.JComboBox();
        btnCheckLoader = new javax.swing.JButton();
        jLabel2 = new javax.swing.JLabel();

        setLayout(new java.awt.GridBagLayout());
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 4;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weighty = 1.0;
        add(jLabel3, gridBagConstraints);

        pHeader.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder(), "Header"));
        pHeader.setLayout(new java.awt.GridBagLayout());

        jlbName.setText("File name:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(4, 4, 0, 0);
        pHeader.add(jlbName, gridBagConstraints);

        jtfName.setFont(new java.awt.Font("Monospaced", 0, 12)); // NOI18N
        jtfName.setToolTipText("File name (follow  the 8.3 rule)");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.weightx = 0.5;
        gridBagConstraints.insets = new java.awt.Insets(4, 4, 0, 0);
        pHeader.add(jtfName, gridBagConstraints);

        jLabel1.setText("Tape mode:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(4, 4, 0, 0);
        pHeader.add(jLabel1, gridBagConstraints);

        jcoMode.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "[SS] Short gaps,single blocks", "[SD] Short gaps,double blocks", "[LS] Long gaps,single blocks", "[LD] Long gaps,double blocks" }));
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.weightx = 0.5;
        gridBagConstraints.insets = new java.awt.Insets(4, 4, 0, 0);
        pHeader.add(jcoMode, gridBagConstraints);

        btnGuessHeader.setMnemonic('h');
        btnGuessHeader.setText("Auto set header");
        btnGuessHeader.setToolTipText("");
        btnGuessHeader.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                onGuessHeader(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 0);
        pHeader.add(btnGuessHeader, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(0, 2, 0, 2);
        add(pHeader, gridBagConstraints);

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

        jlbPauses.setText("Silence list:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 0);
        pBinaryFile.add(jlbPauses, gridBagConstraints);

        jtfPauses.setFont(new java.awt.Font("Monospaced", 0, 12)); // NOI18N
        jtfPauses.setToolTipText("<HTML>\nEnter comma-separated list of silence specifications<br>\nEach silence specification will be used to generate silence or pause the signal generator after an INIT segment<br><br>\nSilence specification can be the following:<br>\nNumber of seconds (e.g. <b>3</b>)<br>\nNumber of seconds followed by P (e.g. <b>3P</b>)<br>\nP (e.g. <b>P</b>)\n</HTML>");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4);
        pBinaryFile.add(jtfPauses, gridBagConstraints);

        jcoBinLoad.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "NONE", "NANOBTAPE", "NANOBTAPE[UR]", "NANOBTAPE[U2]" }));
        jcoBinLoad.setToolTipText("<HTML>\nChoose one of built-in binary loaders that will be prepent<BR>\nUseful for binary files\n<HTML>\n");
        jcoBinLoad.addItemListener(new java.awt.event.ItemListener() {
            public void itemStateChanged(java.awt.event.ItemEvent evt) {
                on_loader_change(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.weighty = 0.1;
        gridBagConstraints.insets = new java.awt.Insets(4, 4, 0, 0);
        pBinaryFile.add(jcoBinLoad, gridBagConstraints);

        btnCheckLoader.setMnemonic('c');
        btnCheckLoader.setText("Check loader");
        btnCheckLoader.setToolTipText("<HTML>\nCheck whether selected binary loader<BR>\nwill be destroyed by input binary file<BR>\n</HTML>");
        btnCheckLoader.setEnabled(false);
        btnCheckLoader.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnCheckLoaderActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
        gridBagConstraints.insets = new java.awt.Insets(4, 4, 0, 4);
        pBinaryFile.add(btnCheckLoader, gridBagConstraints);

        jLabel2.setText("Binary loader:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(4, 4, 0, 0);
        pBinaryFile.add(jLabel2, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 3;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.weightx = 1.0;
        add(pBinaryFile, gridBagConstraints);
    }// </editor-fold>//GEN-END:initComponents

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


        int sl = jcoBinLoad.getSelectedIndex();
        String msg="";
        String fname=ioProvider.getInFile();

        /*Verify tape mode and binary loader*/
        int k = jcoMode.getSelectedIndex();
        int j = jcoBinLoad.getSelectedIndex();

        if ( (k==1 || k==3) && (j==BTapePlugin.BL_NANOBTAPE || j==BTapePlugin.BL_NANOBTAPE_UR || j==BTapePlugin.BL_NANOBTAPE_U2)) {
            msg=MSG_BL_NOT_COMP;
            JOptionPane.showMessageDialog(null, msg,"Binary loader not compatible",JOptionPane.ERROR_MESSAGE);
            return;
        }

        /*Check whether loader won't be destroyed*/
        switch(sl) {
            
            /*NANOBTAPE*/
            case BTapePlugin.BL_NANOBTAPE: {
                msg=Utils.checkForBinaryLoader(fname, 2820, 3434, 1792, 1792+1023,Integer.MAX_VALUE);
                break;
            }
            /*NANOBTAPE[UR]*/
            case BTapePlugin.BL_NANOBTAPE_UR: {
                msg=Utils.checkForBinaryLoader(fname, 1796, 2468, 49152, 49152+1023,Integer.MAX_VALUE);
                break;
            }
            case BTapePlugin.BL_NANOBTAPE_U2: {
                msg=Utils.checkForBinaryLoader(fname, 1796, 2468, 63488, 63488+1023,Integer.MAX_VALUE);
                break;
            }
        }
        JOptionPane.showMessageDialog(null, msg,"Loader check",JOptionPane.INFORMATION_MESSAGE);

    }//GEN-LAST:event_btnCheckLoaderActionPerformed

    private void on_loader_change(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_on_loader_change
        if (evt.getStateChange()==ItemEvent.SELECTED) {
            if (jcoBinLoad.getSelectedIndex()==0) {
                btnCheckLoader.setEnabled(false);
            }
            else {
                btnCheckLoader.setEnabled(true);
            }
        }
    }//GEN-LAST:event_on_loader_change

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

        /*Testing existence*/
        File f = new File(ioProvider.getInFile());
        
        String msg = Utils.checkIfHeaderCanBeSet(f);
        if (msg!=null) {
            JOptionPane.showMessageDialog(null, msg,"Unable to set header",JOptionPane.ERROR_MESSAGE);
            return;
        }

        /*Create 8.3 filename if possible*/
        String nm = f.getName();
        int l = nm.length();

        String fn="";
        String fext="";

        int dotIndex=nm.indexOf('.');

        /*No dot*/
        if (dotIndex==-1) {
            jtfName.setText(nm.substring(0,Math.min(8, nm.length())));
            return;
        }
        
        /*Dot exists*/
        fn = nm.substring(0,dotIndex);
        fext = nm.substring(dotIndex);

        jtfName.setText( fn.substring(0,Math.min(8, fn.length()))+fext.substring(0,Math.min(4, fext.length())) );
  

    }//GEN-LAST:event_onGuessHeader
    
    
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton btnCheckLoader;
    private javax.swing.JButton btnGuessHeader;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JComboBox jcoBinLoad;
    private javax.swing.JComboBox jcoMode;
    private javax.swing.JLabel jlbName;
    private javax.swing.JLabel jlbPauses;
    private javax.swing.JTextField jtfName;
    private javax.swing.JTextField jtfPauses;
    private javax.swing.JPanel pBinaryFile;
    private javax.swing.JPanel pHeader;
    // End of variables declaration//GEN-END:variables
    
    
    void clear() {
        jtfName.setText("");
        jtfPauses.setText("");
        jcoMode.setSelectedIndex(0);
        jcoBinLoad.setSelectedIndex(0);
        
    }
    
    
    public BTapePlayListItem getRecord() {
        int[] pauses = Utils.parseSilenceList(jtfPauses.getText().trim());
        
        boolean db=false;
        boolean lg=false;
        if (jcoMode.getSelectedIndex()>1) lg=true;
        if (jcoMode.getSelectedIndex()==1 || jcoMode.getSelectedIndex()==3) db=true;
        int bl=jcoBinLoad.getSelectedIndex();
        
        return new BTapePlayListItem(ioProvider.getInFile(),ioProvider.getOutFile(),ioProvider.getPulses(),jtfName.getText(),pauses,lg,db,bl);
    }
    
    public void fill(BTapePlayListItem dpr) {
        jtfName.setText(dpr.fname);
        jtfPauses.setText(Utils.silenceListToString(dpr.silenceList));
        
        int k=0;
        if (dpr.doubleBlocks==true) k+=1;
        if (dpr.longGaps==true) k+=2;
        
        switch(k) {
            case 0: jcoMode.setSelectedIndex(0);break;
            case 1: jcoMode.setSelectedIndex(1);break;
            case 2: jcoMode.setSelectedIndex(2);break;
            case 3: jcoMode.setSelectedIndex(3);break;
        }

        jcoBinLoad.setSelectedIndex(dpr.loader);
        
    }
    
    
    public String verify() {

        /*Verify tape mode and binary loader*/
        int k = jcoMode.getSelectedIndex();
        int j = jcoBinLoad.getSelectedIndex();

        if ( (k==1 || k==3) && (j==BTapePlugin.BL_NANOBTAPE || j==BTapePlugin.BL_NANOBTAPE_UR || j==BTapePlugin.BL_NANOBTAPE_U2)) {
            return MSG_BL_NOT_COMP;
        }

        if (Utils.verifyBTapeFileName(jtfName.getText())==true) return null;
        return MSG_NOT_83_FNAME;
        
    }
    
    private static final String MSG_NOT_83_FNAME = "Filename is not in 8.3 form";
    private static final String MSG_BL_NOT_COMP = "Selected binary loader does not support selected tape mode";
}
