package moppydesk.ui;

import java.awt.event.ActionEvent;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import moppydesk.OutputSetting;
import moppydesk.OutputSetting.OutputType;

/**
 *
 * @author Sammy1Am
 */
public class ChannelOutControl extends javax.swing.JPanel {

    private final OutputSetting settings;
    private final MoppyControlWindow controlWindow;

    /**
     * Creates new form ChannelOutControl
     */
    public ChannelOutControl(MoppyControlWindow mcw, OutputSetting os) {
        this.settings = os;
        this.controlWindow = mcw;
        initComponents();        
        loadSettings();
    }

    private void loadSettings() {
        
        if (settings.type.equals(OutputType.MOPPY)) {
            moppyTypeRB.setSelected(true);
            outputTypeChanged(OutputType.MOPPY);
        } else {
            MIDITypeRB.setSelected(true);
            outputTypeChanged(OutputType.MIDI);
        } 
        
        if (settings.enabled) {
            enabledCB.setSelected(true);
            enableControls();
        } else {
            enabledCB.setSelected(false);
            disableControls();
        }      
                    
        //MrSolidSnake745: Ensure the saved settings are still valid and load their values
        //Else default to the first item in the collection
        if(doesCOMExist(settings.comPort)) {comComboBox.setSelectedItem(settings.comPort);}  
        else {settings.comPort = (String) comComboBox.getModel().getElementAt(0);}
                
        if(doesMIDIExist(settings.midiDeviceName)) {midiOutComboBox.setSelectedItem(settings.midiDeviceName);}  
        else {settings.midiDeviceName = (String) midiOutComboBox.getModel().getElementAt(0);}
    }

    public void lockControl(){
        enabledCB.setEnabled(false);
        disableControls();
    }
    
    public void unlockControl(){
        enabledCB.setEnabled(true);
        if (enabledCB.isSelected()) enableControls();
    }
    
    private void disableControls() {
        moppyTypeRB.setEnabled(false);
        MIDITypeRB.setEnabled(false);
        comComboBox.setEnabled(false);
        midiOutComboBox.setEnabled(false);
    }

    private void enableControls() {
        moppyTypeRB.setEnabled(true);
        MIDITypeRB.setEnabled(true);
        if (moppyTypeRB.isSelected()){
            outputTypeChanged(new ActionEvent(moppyTypeRB, ActionEvent.ACTION_PERFORMED, moppyTypeRB.getActionCommand()));
        } else if (MIDITypeRB.isSelected()){
            outputTypeChanged(new ActionEvent(MIDITypeRB, ActionEvent.ACTION_PERFORMED, MIDITypeRB.getActionCommand()));
        }        
    }

    private boolean doesCOMExist(Object obj) {
        return (((DefaultComboBoxModel)(comComboBox.getModel())).getIndexOf(obj) > -1);
    }
    
    private boolean doesMIDIExist(Object obj) {
        return (((DefaultComboBoxModel)(midiOutComboBox.getModel())).getIndexOf(obj) > -1);
    }
    
    //MrSolidSnake745: Method to refresh the list of available COM ports
    private void refreshAvailablePorts() {
        comComboBox.setModel(new DefaultComboBoxModel<String>(moppydesk.outputs.MoppyCOMBridge.getAvailableCOMPorts()));
        if(doesCOMExist(settings.comPort)) {comComboBox.setSelectedItem(settings.comPort);} //To avoid losing last user selected value
        else {settings.comPort = (String) comComboBox.getModel().getElementAt(0);}  //ActionPerformed event isn't triggered so we need to manually set
    }
    
    /**
     * 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() {

        outputTypeRB = new javax.swing.ButtonGroup();
        moppyTypeRB = new javax.swing.JRadioButton();
        MIDITypeRB = new javax.swing.JRadioButton();
        comComboBox = new javax.swing.JComboBox<String>();
        midiOutComboBox = new javax.swing.JComboBox<String>();
        enabledCB = new javax.swing.JCheckBox();

        setPreferredSize(new java.awt.Dimension(525, 23));

        outputTypeRB.add(moppyTypeRB);
        moppyTypeRB.setText("Moppy Serial:");
        moppyTypeRB.setToolTipText("Sends Moppy-protocol serial data to selected COM port");
        moppyTypeRB.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                outputTypeChanged(evt);
            }
        });

        outputTypeRB.add(MIDITypeRB);
        MIDITypeRB.setText("MIDI Out:");
        MIDITypeRB.setToolTipText("Sends MIDI messages through to selected MIDI port");
        MIDITypeRB.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                outputTypeChanged(evt);
            }
        });

        comComboBox.setModel(new DefaultComboBoxModel<String>(moppydesk.outputs.MoppyCOMBridge.getAvailableCOMPorts()));
        comComboBox.addPopupMenuListener(new javax.swing.event.PopupMenuListener() {
            public void popupMenuCanceled(javax.swing.event.PopupMenuEvent evt) {
            }
            public void popupMenuWillBecomeInvisible(javax.swing.event.PopupMenuEvent evt) {
            }
            public void popupMenuWillBecomeVisible(javax.swing.event.PopupMenuEvent evt) {
                comComboBoxPopupMenuWillBecomeVisible(evt);
            }
        });
        comComboBox.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                comComboBoxActionPerformed(evt);
            }
        });

        midiOutComboBox.setModel(new DefaultComboBoxModel<String>(controlWindow.availableMIDIOuts.keySet().toArray(new String[0])));
        midiOutComboBox.setEnabled(false);
        midiOutComboBox.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                midiOutComboBoxActionPerformed(evt);
            }
        });

        enabledCB.setText(String.valueOf(settings.MIDIChannel));
        enabledCB.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                enabledCBActionPerformed(evt);
            }
        });

        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()
                .addComponent(enabledCB, javax.swing.GroupLayout.PREFERRED_SIZE, 46, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(moppyTypeRB)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(comComboBox, 0, 161, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(MIDITypeRB)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(midiOutComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 130, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addGap(0, 0, Short.MAX_VALUE)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(moppyTypeRB)
                    .addComponent(MIDITypeRB)
                    .addComponent(comComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(midiOutComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(enabledCB)))
        );
    }// </editor-fold>//GEN-END:initComponents

    private void comComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_comComboBoxActionPerformed
        //MrSolidSnake745: FYI, this fires on initial click to generate dropdown and once more on clicking a value
        settings.comPort = (String) ((JComboBox) evt.getSource()).getSelectedItem();
    }//GEN-LAST:event_comComboBoxActionPerformed

    private void midiOutComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_midiOutComboBoxActionPerformed
        settings.midiDeviceName = (String) ((JComboBox) evt.getSource()).getSelectedItem();
    }//GEN-LAST:event_midiOutComboBoxActionPerformed

    private void enabledCBActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_enabledCBActionPerformed
        settings.enabled = ((JCheckBox) evt.getSource()).isSelected();
        if (settings.enabled) {
            enableControls();
        } else {
            disableControls();
        }
    }//GEN-LAST:event_enabledCBActionPerformed

    private void outputTypeChanged(OutputType newType){
        settings.type = newType;
        if (newType.equals(OutputType.MOPPY)){
            midiOutComboBox.setEnabled(false);
            comComboBox.setEnabled(true);
        } else {
            comComboBox.setEnabled(false);
            midiOutComboBox.setEnabled(true);
        }
    }
    
    private void outputTypeChanged(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_outputTypeChanged
        if (evt.getSource().equals(moppyTypeRB)) {
            outputTypeChanged(OutputType.MOPPY);
        } else {
            outputTypeChanged(OutputType.MIDI);
        }
    }//GEN-LAST:event_outputTypeChanged

    private void comComboBoxPopupMenuWillBecomeVisible(javax.swing.event.PopupMenuEvent evt) {//GEN-FIRST:event_comComboBoxPopupMenuWillBecomeVisible
        refreshAvailablePorts();
    }//GEN-LAST:event_comComboBoxPopupMenuWillBecomeVisible

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JRadioButton MIDITypeRB;
    private javax.swing.JComboBox<String> comComboBox;
    private javax.swing.JCheckBox enabledCB;
    private javax.swing.JComboBox<String> midiOutComboBox;
    private javax.swing.JRadioButton moppyTypeRB;
    private javax.swing.ButtonGroup outputTypeRB;
    // End of variables declaration//GEN-END:variables
}