/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package turgen;

import java.awt.CardLayout;
import java.awt.Rectangle;
import java.io.File;
import java.io.FileNotFoundException;
import javax.swing.DefaultListModel;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.JSpinner;
import javax.swing.SwingUtilities;
import turgen.dtb.Basic2BinaryEmbedder;

/**
 *
 * @author michael
 */
public class EmbedBasicDialog extends javax.swing.JDialog implements UIPersistor,Logger {

    /**
     * Creates new form EmbedBasicDialog
     */
    public EmbedBasicDialog() {
        initComponents();
        jspBaseAddr.setEditor(new JSpinner.NumberEditor(jspBaseAddr,"#"));
    }
    
    private DefaultListModel basicFileList;

    /**
     * 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;

        jfcBasicFiles = new javax.swing.JFileChooser();
        jfcOutputDirectory = new javax.swing.JFileChooser();
        pCards = new javax.swing.JPanel();
        pMainCard = new javax.swing.JPanel();
        pMainPart = new javax.swing.JPanel();
        pInputControls = new javax.swing.JPanel();
        jspBasicFiles = new javax.swing.JScrollPane();
        jlsBasicFiles = new javax.swing.JList();
        jbtAddBrowse = new javax.swing.JButton();
        jbtRemove = new javax.swing.JButton();
        pOutputControls = new javax.swing.JPanel();
        jtfOutputDirectory = new javax.swing.JTextField();
        jlbOutputDirectory = new javax.swing.JLabel();
        jbtBrowseOutputDirectory = new javax.swing.JButton();
        jlbBaseAddr = new javax.swing.JLabel();
        jspBaseAddr = new javax.swing.JSpinner();
        jcbProtect = new javax.swing.JCheckBox();
        pMainControls = new javax.swing.JPanel();
        jbtEmbed = new javax.swing.JButton();
        jbtCancel = new javax.swing.JButton();
        pReport = new javax.swing.JPanel();
        pReportControls = new javax.swing.JPanel();
        jbtBack = new javax.swing.JButton();
        jbtClose = new javax.swing.JButton();
        jspReport = new javax.swing.JScrollPane();
        jtaReport = new javax.swing.JTextArea();

        jfcBasicFiles.setDialogTitle("Add BASIC files");
        jfcBasicFiles.setMultiSelectionEnabled(true);

        jfcOutputDirectory.setFileSelectionMode(javax.swing.JFileChooser.DIRECTORIES_ONLY);

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        setTitle("Embed tokenized BASIC to binary file");
        setModal(true);

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

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

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

        pInputControls.setBorder(javax.swing.BorderFactory.createTitledBorder("Input BASIC files"));
        pInputControls.setLayout(new java.awt.GridBagLayout());

        jlsBasicFiles.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_INTERVAL_SELECTION);
        jlsBasicFiles.setToolTipText("List of tokenized BASIC files that will be embedded to binary files");
        jspBasicFiles.setViewportView(jlsBasicFiles);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.gridheight = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(0, 4, 0, 0);
        pInputControls.add(jspBasicFiles, gridBagConstraints);

        jbtAddBrowse.setMnemonic('A');
        jbtAddBrowse.setText("Add BASIC files...");
        jbtAddBrowse.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                onAddBasicFile(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHEAST;
        gridBagConstraints.insets = new java.awt.Insets(0, 4, 0, 0);
        pInputControls.add(jbtAddBrowse, gridBagConstraints);

        jbtRemove.setMnemonic('R');
        jbtRemove.setText("Remove selected");
        jbtRemove.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                onRemoveSelected(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHEAST;
        gridBagConstraints.insets = new java.awt.Insets(0, 4, 0, 0);
        pInputControls.add(jbtRemove, gridBagConstraints);

        pMainPart.add(pInputControls, java.awt.BorderLayout.CENTER);

        pOutputControls.setBorder(javax.swing.BorderFactory.createTitledBorder("Output settings"));
        pOutputControls.setLayout(new java.awt.GridBagLayout());
        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 = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(0, 4, 0, 0);
        pOutputControls.add(jtfOutputDirectory, gridBagConstraints);

        jlbOutputDirectory.setText("Output directory:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(0, 4, 0, 0);
        pOutputControls.add(jlbOutputDirectory, gridBagConstraints);

        jbtBrowseOutputDirectory.setMnemonic('B');
        jbtBrowseOutputDirectory.setText("Browse");
        jbtBrowseOutputDirectory.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                onOutDirBrowse(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 3;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
        gridBagConstraints.insets = new java.awt.Insets(0, 4, 0, 0);
        pOutputControls.add(jbtBrowseOutputDirectory, gridBagConstraints);

        jlbBaseAddr.setText("Base address:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(0, 4, 0, 0);
        pOutputControls.add(jlbBaseAddr, gridBagConstraints);

        jspBaseAddr.setModel(new javax.swing.SpinnerNumberModel(8192, 512, 40960, 1));
        jspBaseAddr.setToolTipText("Base address to which the tokenized code will be loaded");
        jspBaseAddr.setValue(Integer.valueOf(2048));
        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);
        pOutputControls.add(jspBaseAddr, gridBagConstraints);

        jcbProtect.setText("Protect against listing:");
        jcbProtect.setToolTipText("Disable BREAK key and set the COLDST flag");
        jcbProtect.setHorizontalTextPosition(javax.swing.SwingConstants.LEFT);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(0, 4, 0, 0);
        pOutputControls.add(jcbProtect, gridBagConstraints);

        pMainPart.add(pOutputControls, java.awt.BorderLayout.SOUTH);

        pMainCard.add(pMainPart, java.awt.BorderLayout.CENTER);

        jbtEmbed.setMnemonic('E');
        jbtEmbed.setText("Embed");
        jbtEmbed.setToolTipText("");
        jbtEmbed.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                onEmbed(evt);
            }
        });
        pMainControls.add(jbtEmbed);

        jbtCancel.setMnemonic('C');
        jbtCancel.setText("Cancel");
        jbtCancel.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                onCancel(evt);
            }
        });
        pMainControls.add(jbtCancel);

        pMainCard.add(pMainControls, java.awt.BorderLayout.SOUTH);

        pCards.add(pMainCard, "main");

        pReport.setBorder(javax.swing.BorderFactory.createTitledBorder("Report"));
        pReport.setLayout(new java.awt.BorderLayout());

        jbtBack.setMnemonic('B');
        jbtBack.setText("Back");
        jbtBack.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                onBack(evt);
            }
        });
        pReportControls.add(jbtBack);

        jbtClose.setMnemonic('C');
        jbtClose.setText("Close");
        jbtClose.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                onClose(evt);
            }
        });
        pReportControls.add(jbtClose);

        pReport.add(pReportControls, java.awt.BorderLayout.SOUTH);

        jtaReport.setColumns(40);
        jtaReport.setFont(new java.awt.Font("Monospaced", 0, 12)); // NOI18N
        jtaReport.setRows(15);
        jspReport.setViewportView(jtaReport);

        pReport.add(jspReport, java.awt.BorderLayout.CENTER);

        pCards.add(pReport, "report");

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

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

    private void onAddBasicFile(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_onAddBasicFile
        
        File[] blank = new File[1];
        blank[0]=new File("");
        /*Display the dialog*/
        jfcBasicFiles.setSelectedFiles(blank);
        int option=jfcBasicFiles.showOpenDialog(this);
        if (option!=JFileChooser.APPROVE_OPTION) return;
        
        File[] files = jfcBasicFiles.getSelectedFiles();
        for(int i=0;i<files.length;i++) {
            basicFileList.addElement(files[i].getAbsolutePath());
        }
        
    }//GEN-LAST:event_onAddBasicFile

    private void onRemoveSelected(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_onRemoveSelected
        if (jlsBasicFiles.getSelectionModel().isSelectionEmpty()==true) return;
        basicFileList.removeRange(jlsBasicFiles.getSelectionModel().getMinSelectionIndex(), jlsBasicFiles.getSelectionModel().getMaxSelectionIndex());
    }//GEN-LAST:event_onRemoveSelected

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

    private void onEmbed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_onEmbed
        
        /*Check if something in the model*/
        int nItems = jlsBasicFiles.getModel().getSize();
        if (nItems<1) {
            JOptionPane.showMessageDialog(this, "No BASIC files selected for embedding", "No BASIC files selected", JOptionPane.WARNING_MESSAGE);
            return;
        }
        
        String outDir="";
        
        /*Check output directory*/
        try {
            File f = new File(jtfOutputDirectory.getText().trim());
            if (f.exists() && f.isDirectory()) {
                outDir=f.getCanonicalPath();
            }
            else {
                throw new FileNotFoundException("Output directory does not exist");
            }
            
        }
        catch(Exception e) {
            JOptionPane.showMessageDialog(this, Utils.getExceptionMessage(e), "Output directory error", JOptionPane.ERROR_MESSAGE);
            e.printStackTrace();
            return;
        }
        
        /*Prepare list of BASIC files*/
        String[] bFiles = new String[nItems];
        for(int i=0;i<nItems;i++) {
            bFiles[i]=(String)jlsBasicFiles.getModel().getElementAt(i);
        }
        
        /*Pack and report*/
        switchCard("report");
        Basic2BinaryEmbedder packer = new Basic2BinaryEmbedder(outDir,bFiles , ((Integer)jspBaseAddr.getValue()).intValue(), this,jcbProtect.isSelected());
        packer.embedFiles();
    }//GEN-LAST:event_onEmbed

    private void onClose(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_onClose
        onCancel(evt);
    }//GEN-LAST:event_onClose

    private void onBack(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_onBack
        switchCard("main");
    }//GEN-LAST:event_onBack

    private void onOutDirBrowse(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_onOutDirBrowse
        int option = jfcOutputDirectory.showOpenDialog(this);
        if (option!=JFileChooser.APPROVE_OPTION) return;
        File f = jfcOutputDirectory.getSelectedFile();
        if (f==null) return;
        jtfOutputDirectory.setText(f.getAbsolutePath());
        
    
    }//GEN-LAST:event_onOutDirBrowse

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        

        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new EmbedBasicDialog().setVisible(true);
            }
        });
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton jbtAddBrowse;
    private javax.swing.JButton jbtBack;
    private javax.swing.JButton jbtBrowseOutputDirectory;
    private javax.swing.JButton jbtCancel;
    private javax.swing.JButton jbtClose;
    private javax.swing.JButton jbtEmbed;
    private javax.swing.JButton jbtRemove;
    private javax.swing.JCheckBox jcbProtect;
    private javax.swing.JFileChooser jfcBasicFiles;
    private javax.swing.JFileChooser jfcOutputDirectory;
    private javax.swing.JLabel jlbBaseAddr;
    private javax.swing.JLabel jlbOutputDirectory;
    private javax.swing.JList jlsBasicFiles;
    private javax.swing.JSpinner jspBaseAddr;
    private javax.swing.JScrollPane jspBasicFiles;
    private javax.swing.JScrollPane jspReport;
    private javax.swing.JTextArea jtaReport;
    private javax.swing.JTextField jtfOutputDirectory;
    private javax.swing.JPanel pCards;
    private javax.swing.JPanel pInputControls;
    private javax.swing.JPanel pMainCard;
    private javax.swing.JPanel pMainControls;
    private javax.swing.JPanel pMainPart;
    private javax.swing.JPanel pOutputControls;
    private javax.swing.JPanel pReport;
    private javax.swing.JPanel pReportControls;
    // End of variables declaration//GEN-END:variables
    
    
    public void setVisible(boolean b) {
        
        if (b==true) {
            basicFileList = new DefaultListModel();
            jlsBasicFiles.setModel(basicFileList);
            clear();
            switchCard("main");
        }
        super.setVisible(b);
        
    }
    
    public Object[] getPersistenceData() {
        Object[] pData = new Object[6];
        pData[0]=jfcBasicFiles.getCurrentDirectory().getAbsolutePath();
        pData[1]=jfcOutputDirectory.getCurrentDirectory().getAbsolutePath();
        pData[2]=jtfOutputDirectory.getText();
        pData[3]=jspBaseAddr.getValue();
        pData[4]=this.getBounds();
        pData[5]=Boolean.valueOf(jcbProtect.isSelected());
        return pData;
        
    }

    public void setPersistenceData(Object[] data) throws Exception {
        jfcBasicFiles.setCurrentDirectory(new File((String)data[0]));
        jfcOutputDirectory.setCurrentDirectory(new File((String)data[1]));
        jtfOutputDirectory.setText((String)data[2]);
        jspBaseAddr.setValue(data[3]);
        this.setBounds((Rectangle)data[4]);
        jcbProtect.setSelected(((Boolean)data[5]).booleanValue());
    }

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

    public void setPersistenceDefaults() {
        pack();
        DialogManager.centerContainer(this);
    }

    void updateFileDialogUI() {
        SwingUtilities.updateComponentTreeUI(jfcBasicFiles);
        SwingUtilities.updateComponentTreeUI(jfcOutputDirectory);
    }

    public void addMessage(String s, boolean fromExtThread) {
        jtaReport.append(s);
    }

    public void clear() {
        jtaReport.setText("");
    }

    public void impulse(boolean fromExtThread) {
        
    }
    
    private void switchCard(String cardName) {
        CardLayout cl = (CardLayout)pCards.getLayout();
        cl.show(pCards, cardName);    
    }
}
