package turgen.tapeimageextractor;

import java.awt.event.ItemEvent;
import java.io.File;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import turgen.Utils;
import turgen.dtb.DOS2BinaryException;


/**
 *
 * @author michael
 */
public class ExtractBinaryDialog extends javax.swing.JDialog {
    
    
    private TapeImageModel tapeImage;
    private int[] selectedIndexes;
    
    /**
     * Creates new form ExtractBinaryDialog
     */
    public ExtractBinaryDialog(JDialog parent) {
        super(parent);
        setModal(true);
        initComponents();
        
    }
    
    public void setVisible(boolean visible) {
        super.setVisible(visible);
        jlbAutoDetectionResult.setText("");
    }

    /**
     * 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.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {
        java.awt.GridBagConstraints gridBagConstraints;

        jbgSettings = new javax.swing.ButtonGroup();
        pMainControls = new javax.swing.JPanel();
        fcOutputFile = new javax.swing.JFileChooser();
        pSettings = new javax.swing.JPanel();
        jrbBootFile = new javax.swing.JRadioButton();
        jrbBinaryFile = new javax.swing.JRadioButton();
        jrbPlainData = new javax.swing.JRadioButton();
        jbtAutoDetect = new javax.swing.JButton();
        jlbLoadAddress = new javax.swing.JLabel();
        jlbRunAddress = new javax.swing.JLabel();
        jspLoadAddr = new javax.swing.JSpinner();
        jspRunAddr = new javax.swing.JSpinner();
        pFiller = new javax.swing.JPanel();
        jlbAutoDetectionResult = new javax.swing.JLabel();
        pButtons = new javax.swing.JPanel();

        setTitle("Extract data to binary file");

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

        fcOutputFile.setDialogType(javax.swing.JFileChooser.SAVE_DIALOG);
        fcOutputFile.setApproveButtonText("Extract");
        fcOutputFile.setBorder(javax.swing.BorderFactory.createTitledBorder("Output file"));
        fcOutputFile.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                onFileChooserButtonPressed(evt);
            }
        });
        pMainControls.add(fcOutputFile, java.awt.BorderLayout.CENTER);

        pSettings.setBorder(javax.swing.BorderFactory.createTitledBorder("Settings"));
        pSettings.setLayout(new java.awt.GridBagLayout());

        jbgSettings.add(jrbBootFile);
        jrbBootFile.setMnemonic('t');
        jrbBootFile.setSelected(true);
        jrbBootFile.setText("Extract boot file");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(0, 4, 0, 0);
        pSettings.add(jrbBootFile, gridBagConstraints);

        jbgSettings.add(jrbBinaryFile);
        jrbBinaryFile.setMnemonic('b');
        jrbBinaryFile.setText("Extract binary file");
        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);
        pSettings.add(jrbBinaryFile, gridBagConstraints);

        jbgSettings.add(jrbPlainData);
        jrbPlainData.setMnemonic('p');
        jrbPlainData.setText("Extract plain data");
        jrbPlainData.setToolTipText("");
        jrbPlainData.addItemListener(new java.awt.event.ItemListener() {
            public void itemStateChanged(java.awt.event.ItemEvent evt) {
                onExtractPlainDataChanged(evt);
            }
        });
        jrbPlainData.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jrbPlainDataActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(0, 4, 0, 0);
        pSettings.add(jrbPlainData, gridBagConstraints);

        jbtAutoDetect.setMnemonic('A');
        jbtAutoDetect.setText("Auto detect");
        jbtAutoDetect.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                onAutoDetect(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 3;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(0, 4, 0, 0);
        pSettings.add(jbtAutoDetect, gridBagConstraints);

        jlbLoadAddress.setText("Load address:");
        jlbLoadAddress.setEnabled(false);
        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);
        pSettings.add(jlbLoadAddress, gridBagConstraints);

        jlbRunAddress.setText("Run address:");
        jlbRunAddress.setEnabled(false);
        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);
        pSettings.add(jlbRunAddress, gridBagConstraints);

        jspLoadAddr.setModel(new javax.swing.SpinnerNumberModel(0, 0, 65534, 1));
        jspLoadAddr.setEnabled(false);
        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);
        pSettings.add(jspLoadAddr, gridBagConstraints);

        jspRunAddr.setModel(new javax.swing.SpinnerNumberModel(-1, -1, 65535, 1));
        jspRunAddr.setEnabled(false);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 4;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(0, 4, 0, 0);
        pSettings.add(jspRunAddr, gridBagConstraints);

        javax.swing.GroupLayout pFillerLayout = new javax.swing.GroupLayout(pFiller);
        pFiller.setLayout(pFillerLayout);
        pFillerLayout.setHorizontalGroup(
            pFillerLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 0, Short.MAX_VALUE)
        );
        pFillerLayout.setVerticalGroup(
            pFillerLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 0, Short.MAX_VALUE)
        );

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 5;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.gridheight = 4;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        pSettings.add(pFiller, gridBagConstraints);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 3;
        gridBagConstraints.gridwidth = 4;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(0, 4, 0, 0);
        pSettings.add(jlbAutoDetectionResult, gridBagConstraints);

        pMainControls.add(pSettings, java.awt.BorderLayout.NORTH);

        getContentPane().add(pMainControls, java.awt.BorderLayout.CENTER);
        getContentPane().add(pButtons, java.awt.BorderLayout.SOUTH);

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

    private void jrbPlainDataActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jrbPlainDataActionPerformed
        // TODO add your handling code here:
    }//GEN-LAST:event_jrbPlainDataActionPerformed

    private void onExtractPlainDataChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_onExtractPlainDataChanged
        boolean b = (evt.getStateChange()==ItemEvent.SELECTED);
        jlbLoadAddress.setEnabled(b);
        jlbRunAddress.setEnabled(b);
        jspLoadAddr.setEnabled(b);
        jspRunAddr.setEnabled(b);
    }//GEN-LAST:event_onExtractPlainDataChanged

    private void onAutoDetect(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_onAutoDetect
        
        /*Check for boot file*/
        if (tapeImage.isSelectionBootFile(selectedIndexes)) {
            jrbBootFile.setSelected(true);
            jlbAutoDetectionResult.setText("Selected chunks appear to contain a boot file");
            return;
        }
        if (tapeImage.isSelectionBinaryFile(selectedIndexes)) {
            jrbBinaryFile.setSelected(true);
            jlbAutoDetectionResult.setText("Selected chunks appear to conatin a binary file");
            return;
        }
        jrbPlainData.setSelected(true);
        jlbAutoDetectionResult.setText("Selected chunks appear to contain plain data");
        
    }//GEN-LAST:event_onAutoDetect

    private void onFileChooserButtonPressed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_onFileChooserButtonPressed
        JFileChooser fc = (JFileChooser) evt.getSource();
        String command = evt.getActionCommand();

        
        if (command.equals(JFileChooser.APPROVE_SELECTION)) {
            File f = fc.getSelectedFile();

            if (f == null || (f.exists() && !f.isFile()) ) {
                JOptionPane.showMessageDialog(this, "Unable to extract data. No output file selected.", "No output file", JOptionPane.ERROR_MESSAGE);
                return;
            }

            try {
                if (jrbBinaryFile.isSelected()) {
                    tapeImage.extractBinaryFile(selectedIndexes, f.getAbsolutePath());
                }
                else if (jrbBootFile.isSelected()) {
                    tapeImage.extractBootFile(selectedIndexes, f.getAbsolutePath());
                }
                else if (jrbPlainData.isSelected()) {
                    int loadAddr = ((Integer) jspLoadAddr.getValue()).intValue();
                    int runAddr = ((Integer) jspRunAddr.getValue()).intValue();
                    tapeImage.extractPlainDataFile(selectedIndexes, f.getAbsolutePath(), loadAddr, runAddr);
                }

                setVisible(false);
                dispose();

            } 
            catch (DOS2BinaryException dtbe) {
                JOptionPane.showMessageDialog(this, dtbe.getFormattedMessage(), "Unable to extract data", JOptionPane.ERROR_MESSAGE);
            }
            
            catch (Exception e) {
                JOptionPane.showMessageDialog(this, Utils.getTitledExceptionMessage("Unable to extract data", e), "Unable to extract data", JOptionPane.ERROR_MESSAGE);
            }
        }
        else {
            setVisible(false);
            dispose();
        }
    }//GEN-LAST:event_onFileChooserButtonPressed

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /* Set the Nimbus look and feel */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(ExtractBinaryDialog.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(ExtractBinaryDialog.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(ExtractBinaryDialog.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(ExtractBinaryDialog.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new ExtractBinaryDialog(null).setVisible(true);
            }
        });
    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JFileChooser fcOutputFile;
    private javax.swing.ButtonGroup jbgSettings;
    private javax.swing.JButton jbtAutoDetect;
    private javax.swing.JLabel jlbAutoDetectionResult;
    private javax.swing.JLabel jlbLoadAddress;
    private javax.swing.JLabel jlbRunAddress;
    private javax.swing.JRadioButton jrbBinaryFile;
    private javax.swing.JRadioButton jrbBootFile;
    private javax.swing.JRadioButton jrbPlainData;
    private javax.swing.JSpinner jspLoadAddr;
    private javax.swing.JSpinner jspRunAddr;
    private javax.swing.JPanel pButtons;
    private javax.swing.JPanel pFiller;
    private javax.swing.JPanel pMainControls;
    private javax.swing.JPanel pSettings;
    // End of variables declaration//GEN-END:variables

    Object getDirectory() {
        return fcOutputFile.getCurrentDirectory().getAbsolutePath();
    }

    void setDirectory(String extractBinaryDirectory) {
        if (extractBinaryDirectory!=null) {
            fcOutputFile.setCurrentDirectory(new File(extractBinaryDirectory));
        }
    }
    
    void setTapeImage(TapeImageModel tapeImage,int[] selectedIndexes) {
        this.tapeImage=tapeImage;
        this.selectedIndexes=selectedIndexes;
    }
}
