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

import compose.PolyphonGeneticComposer;
import data.AverageMIDIFileData;
import data.IInstrument;
import data.IScore;
import data.ITonality;
import data.MIDIInstrumentData;
import database.DatabaseInterface;
import java.awt.Rectangle;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.table.DefaultTableModel;
import jm.music.data.Score;
import jm.util.Write;
import midi.MIDIAnalyser;
import midi.MIDIPlayer;

/**
 *
 * @author Tom
 */
public class PolyphoneComposingDialog extends javax.swing.JDialog {
    private String user = ""; //username
    private String pw = ""; //password
    private String url = ""; //DB-Url
    private HashMap<String, Integer> categories = new HashMap<>(); //List or categories ordered
    private Score score = null; //die Komposition
    private PolyphonGeneticComposer pgc = null;
    private ComposingStatusDialog csd = null;
    
    /**
     * Creates new form PolyphoneComposingDialog
     */
    public PolyphoneComposingDialog(java.awt.Frame parent, boolean modal, String user, String pw, String url, String path) {
        super(parent, modal);
        initComponents();
        
        this.user = user;
        this.pw = pw;
        this.url = url;
        
        Rectangle parentBounds = parent.getBounds();
        this.setBounds((int)(parentBounds.getWidth()/2-getBounds().getWidth()/2) + (int)parentBounds.getX(), 
                       (int)(parentBounds.getHeight()/2-getBounds().getHeight()/2) + (int)parentBounds.getY(), 
                       (int)getBounds().getWidth(), (int)getBounds().getHeight());
        
        DatabaseInterface dbi = new DatabaseInterface(user, pw, url);
        LinkedHashMap<String, Integer> cat = dbi.getCategoriesOrdered();
        Iterator it = cat.entrySet().iterator();
        while (it.hasNext()) {
           Map.Entry pairs = (Map.Entry)it.next();
           cmbCategory.addItem(pairs.getKey());
           categories.put(pairs.getKey().toString(), (int)pairs.getValue());
        }
        
        //Comboboxen Instrumentengruppen und Instrumente fuellen
        AverageMIDIFileData avgData = new AverageMIDIFileData();
        LinkedHashMap<String, Integer> lhm = avgData.getInstrumentGroup();
        Iterator it2 = lhm.entrySet().iterator();
        while (it2.hasNext()) {
           Map.Entry pair = (Map.Entry)it2.next();
           cmbInstrumentGroup.addItem(pair.getKey());
        }
        
        //Startwerte setzen
        spTempo.setValue(120);
        spPopulation.setValue(5);
        sldLength.setMinimum(10);
        sldLength.setMaximum(300);
        sldLength.setValue(120);
        sldVolume.setMinimum(0);
        sldVolume.setMaximum(100);
        sldVolume.setValue(50);
        sldInstrumentCount.setMinimum(1);
        sldInstrumentCount.setMaximum(10);
        sldInstrumentCount.setValue(4);
        sldFitness.setMinimum(0);
        sldFitness.setMaximum(70);
        sldFitness.setValue(35);
        chkCrossover.setSelected(true);
        chkNPointCrossover.setSelected(true);
        chkMutation.setSelected(true);
        
        fillInstrumentTable();
        fillKeys();
    }

    /**
     * befuellt die Instrumente der ausgewaehlten Kategorie
     */
    private void fillInstrumentTable(){
        if (!categories.isEmpty() && categories.containsKey(cmbCategory.getSelectedItem().toString())) {
            int cat = categories.get(cmbCategory.getSelectedItem().toString());
            DatabaseInterface dbI = new DatabaseInterface(user, pw, url);
            
            //Instrumente vorschlagen
            ArrayList<IInstrument> ali = dbI.getInstruments(cat);
            dbI.closeConnection();
            DefaultTableModel tableModel = (DefaultTableModel)tabInstruments.getModel();
            //Tabelle loeschen
            int rowCount = tableModel.getRowCount();
            for(int l = 0; l < rowCount; l++)
            {
               tableModel.removeRow(0);
            }
            //Tabelle befuellen
            if (sldInstrumentCount.getValue() == 1 || sldInstrumentCount.getValue() == 10){
                for (int i=0; i<ali.size() && i<sldInstrumentCount.getValue(); i++){
                    IInstrument ii = ali.get(i);
                    if (i==9){
                        tableModel.insertRow(tableModel.getRowCount(), new Object[]{"Percussion","Percussion",100});
                    } else {
                        tableModel.insertRow(tableModel.getRowCount(), new Object[]{ii.getInstrument(),ii.getInstrument(),100});
                    }
                }
                if (ali.size() < sldInstrumentCount.getValue()){
                    tableModel.insertRow(tableModel.getRowCount(), new Object[]{"Percussion","Percussion",100});
                }
            } else { //das letzte Instrument sind immer Percussion
                for (int i=0; i<ali.size()-1 && i<sldInstrumentCount.getValue()-1; i++){
                    IInstrument ii = ali.get(i);
                    tableModel.insertRow(tableModel.getRowCount(), new Object[]{ii.getInstrument(),ii.getInstrument(),100});
                }
                if (ali.size() < sldInstrumentCount.getValue()){
                    IInstrument ii = ali.get(ali.size()-1);
                    tableModel.insertRow(tableModel.getRowCount(), new Object[]{ii.getInstrument(),ii.getInstrument(),100});
                }
                tableModel.insertRow(tableModel.getRowCount(), new Object[]{"Percussion","Percussion",100});
            }
        }
    }
    
    /**
     * befuellt die Combobox mit den Tonarten sortiert nach Auftreten innerhalb der Kategorie
     */
    private void fillKeys(){
        if (!categories.isEmpty() && categories.containsKey(cmbCategory.getSelectedItem().toString())) {
            int cat = categories.get(cmbCategory.getSelectedItem().toString());
            DatabaseInterface dbi = new DatabaseInterface(user, pw, url);
            ArrayList<ITonality> ito = dbi.getTonalities(cat);
            cmbKey.removeAllItems();
            for (ITonality t : ito) {
               if (t.isMajor()) {
                  cmbKey.addItem(t.getKey() +" major");
               } else {
                  cmbKey.addItem(t.getKey() +" minor");
               }
            }
            dbi.closeConnection();
        }
    }
    
    /**
     * aktualisiert die Instrumente der ausgewaehlten Kategorie
     */
    private void updateInstrumentTable(){
        if (!categories.isEmpty() && categories.containsKey(cmbCategory.getSelectedItem().toString())) {
            int cat = categories.get(cmbCategory.getSelectedItem().toString());
            DatabaseInterface dbI = new DatabaseInterface(user, pw, url);
            
            //Instrumente vorschlagen
            ArrayList<IInstrument> ali = dbI.getInstruments(cat);
            dbI.closeConnection();
            DefaultTableModel tableModel = (DefaultTableModel)tabInstruments.getModel();
            //Tabelle merken und loeschen
            int rowCount = tableModel.getRowCount();
            int PercussionVolume = 100;
            if (tableModel.getRowCount() > 0 && tableModel.getValueAt(rowCount-1, 0).toString().equalsIgnoreCase("Percussion")){
                PercussionVolume = (int)tableModel.getValueAt(rowCount-1, 2);
            }
            String[] sArr = new String[rowCount];
            int[] iArr = new int[rowCount];
            for(int l = 0; l < rowCount; l++)
            {
               sArr[l] = tableModel.getValueAt(0, 1).toString();
               iArr[l] = (int)tableModel.getValueAt(0, 2);
               tableModel.removeRow(0);
            }
            //Tabelle befuellen
            if (sldInstrumentCount.getValue() == 1 || sldInstrumentCount.getValue() == 10){
                for (int i=0; i<ali.size() && i<sldInstrumentCount.getValue(); i++){
                    IInstrument ii = ali.get(i);
                    if (i==9){
                        tableModel.insertRow(tableModel.getRowCount(), new Object[]{"Percussion","Percussion",PercussionVolume});
                    } else {
                        tableModel.insertRow(tableModel.getRowCount(), new Object[]{ii.getInstrument(),ii.getInstrument(),100});
                    }
                }
                if (ali.size() < sldInstrumentCount.getValue()){
                    tableModel.insertRow(tableModel.getRowCount(), new Object[]{"Percussion","Percussion",PercussionVolume});
                }
            } else { //das letzte Instrument sind immer Percussion
                for (int i=0; i<ali.size()-1 && i<sldInstrumentCount.getValue()-1; i++){
                    IInstrument ii = ali.get(i);
                    tableModel.insertRow(tableModel.getRowCount(), new Object[]{ii.getInstrument(),ii.getInstrument(),100});
                }
                if (ali.size() < sldInstrumentCount.getValue()){
                    IInstrument ii = ali.get(ali.size()-1);
                    tableModel.insertRow(tableModel.getRowCount(), new Object[]{ii.getInstrument(),ii.getInstrument(),100});
                }
                tableModel.insertRow(tableModel.getRowCount(), new Object[]{"Percussion","Percussion",PercussionVolume});
            }
            //alte Werte wieder schreiben
            rowCount = tableModel.getRowCount();
            for(int l = 0; l < rowCount && l < sArr.length-1; l++)
            {
                tableModel.setValueAt(sArr[l], l, 1);
                tableModel.setValueAt(iArr[l], l, 2);
            }
            if (rowCount > 1){
                tableModel.setValueAt("Percussion", rowCount-1, 1);
                tableModel.setValueAt(PercussionVolume, rowCount-1, 2);
            }
        }
    }
    
    /**
     * befuellt die Combobox mit den Instrumenten der Instrumentengruppe
     * @param instrumentgroup 
     */
    private void updateInstrumentCombobox(String instrumentgroup){
        MIDIInstrumentData mid = new MIDIInstrumentData();
        switch (instrumentgroup) {
            case "Piano":
                fillInstrumentsCombobox(mid.getPianos());
                break;
            case "Chromatic Percussion":
                fillInstrumentsCombobox(mid.getChromaticpercussion());
                break;
            case "Organ":
                fillInstrumentsCombobox(mid.getOrgans());
                break;
            case "Guitar":
                fillInstrumentsCombobox(mid.getGuitars());
                break;
            case "Bass":
                fillInstrumentsCombobox(mid.getBasses());
                break;
            case "Strings":
                fillInstrumentsCombobox(mid.getStrings());
                break;
            case "Ensemble":
                fillInstrumentsCombobox(mid.getEnsembles());
                break;
            case "Brass":
                fillInstrumentsCombobox(mid.getBrasses());
                break;
            case "Reed":
                fillInstrumentsCombobox(mid.getReeds());
                break;
            case "Pipe":
                fillInstrumentsCombobox(mid.getPipes());
                break;
            case "Synth Lead":
                fillInstrumentsCombobox(mid.getSynthleads());
                break;
            case "Synth Pad":
                fillInstrumentsCombobox(mid.getSynthpads());
                break;
            case "Synth Effects":
                fillInstrumentsCombobox(mid.getSyntheffects());
                break;
            case "Ethnic":
                fillInstrumentsCombobox(mid.getEthnics());
                break;
            case "Percussive":
                fillInstrumentsCombobox(mid.getPercussivs());
                break;
            case "Sound Effects":
                fillInstrumentsCombobox(mid.getSoundeffects());
                break;
            case "Percussions":
                cmbInstrument.removeAllItems();
                cmbInstrument.addItem("Percussion");
                break;
         }
    }
    
    /**
     * befuellt die Combobox mit den Instrumenten der Hashmap
     * @param lhm LinkedHashMap mit den Instrumenten der Gruppe
     */
    private void fillInstrumentsCombobox(LinkedHashMap<String, Integer> lhm){
        cmbInstrument.removeAllItems();
        Iterator it = lhm.entrySet().iterator();
        while (it.hasNext()) {
           Map.Entry pair = (Map.Entry)it.next();
           cmbInstrument.addItem(pair.getKey());
        }
    }
    
    /**
     * 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() {

        jLabel1 = new javax.swing.JLabel();
        cmbCategory = new javax.swing.JComboBox();
        sldInstrumentCount = new javax.swing.JSlider();
        jLabel2 = new javax.swing.JLabel();
        btnCompose = new javax.swing.JButton();
        btnCancel = new javax.swing.JButton();
        sldLength = new javax.swing.JSlider();
        jLabel5 = new javax.swing.JLabel();
        pnlInstruments = new javax.swing.JPanel();
        jScrollPane1 = new javax.swing.JScrollPane();
        tabInstruments = new javax.swing.JTable();
        cmbInstrumentGroup = new javax.swing.JComboBox();
        cmbInstrument = new javax.swing.JComboBox();
        jLabel3 = new javax.swing.JLabel();
        jLabel4 = new javax.swing.JLabel();
        btnChange = new javax.swing.JButton();
        btnReset = new javax.swing.JButton();
        btnAddPart = new javax.swing.JButton();
        sldVolume = new javax.swing.JSlider();
        lblVolume = new javax.swing.JLabel();
        jLabel9 = new javax.swing.JLabel();
        btnChangeVolume = new javax.swing.JButton();
        lblTempo = new javax.swing.JLabel();
        spTempo = new javax.swing.JSpinner();
        lblInstrumentCount = new javax.swing.JLabel();
        lblLength = new javax.swing.JLabel();
        jLabel6 = new javax.swing.JLabel();
        cmbKey = new javax.swing.JComboBox();
        spPopulation = new javax.swing.JSpinner();
        lblTempo1 = new javax.swing.JLabel();
        jPanel1 = new javax.swing.JPanel();
        btnPlay = new javax.swing.JButton();
        btnSave = new javax.swing.JButton();
        btnStop = new javax.swing.JButton();
        jLabel7 = new javax.swing.JLabel();
        sldFitness = new javax.swing.JSlider();
        lblFitness = new javax.swing.JLabel();
        chkCrossover = new javax.swing.JCheckBox();
        chkNPointCrossover = new javax.swing.JCheckBox();
        chkMutation = new javax.swing.JCheckBox();
        jLabel8 = new javax.swing.JLabel();

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        setTitle("Polyphonic MIDI Composer");
        setResizable(false);
        addWindowListener(new java.awt.event.WindowAdapter() {
            public void windowClosing(java.awt.event.WindowEvent evt) {
                formWindowClosing(evt);
            }
        });

        jLabel1.setText("Category:");

        cmbCategory.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                cmbCategoryActionPerformed(evt);
            }
        });

        sldInstrumentCount.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                sldInstrumentCountStateChanged(evt);
            }
        });

        jLabel2.setText("Instruments:");

        btnCompose.setText("Compose");
        btnCompose.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnComposeActionPerformed(evt);
            }
        });

        btnCancel.setText("Close");
        btnCancel.setMaximumSize(new java.awt.Dimension(77, 23));
        btnCancel.setMinimumSize(new java.awt.Dimension(77, 23));
        btnCancel.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnCancelActionPerformed(evt);
            }
        });

        sldLength.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                sldLengthStateChanged(evt);
            }
        });

        jLabel5.setText("Length:");

        pnlInstruments.setBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.LOWERED));

        tabInstruments.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {

            },
            new String [] {
                "Default", "Used", "Volume"
            }
        ) {
            Class[] types = new Class [] {
                java.lang.String.class, java.lang.String.class, java.lang.Integer.class
            };
            boolean[] canEdit = new boolean [] {
                false, false, false
            };

            public Class getColumnClass(int columnIndex) {
                return types [columnIndex];
            }

            public boolean isCellEditable(int rowIndex, int columnIndex) {
                return canEdit [columnIndex];
            }
        });
        tabInstruments.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                tabInstrumentsMouseClicked(evt);
            }
        });
        jScrollPane1.setViewportView(tabInstruments);

        cmbInstrumentGroup.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                cmbInstrumentGroupActionPerformed(evt);
            }
        });

        jLabel3.setText("Instrumentgroups:");

        jLabel4.setText("Instruments:");

        btnChange.setText("Change");
        btnChange.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnChangeActionPerformed(evt);
            }
        });

        btnReset.setText("Reset");
        btnReset.setPreferredSize(new java.awt.Dimension(69, 23));
        btnReset.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnResetActionPerformed(evt);
            }
        });

        btnAddPart.setText("Add");
        btnAddPart.setPreferredSize(new java.awt.Dimension(69, 23));
        btnAddPart.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnAddPartActionPerformed(evt);
            }
        });

        sldVolume.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                sldVolumeStateChanged(evt);
            }
        });

        lblVolume.setText("50");

        jLabel9.setText("Volume:");

        btnChangeVolume.setText("Change");
        btnChangeVolume.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnChangeVolumeActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout pnlInstrumentsLayout = new javax.swing.GroupLayout(pnlInstruments);
        pnlInstruments.setLayout(pnlInstrumentsLayout);
        pnlInstrumentsLayout.setHorizontalGroup(
            pnlInstrumentsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(pnlInstrumentsLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(pnlInstrumentsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(pnlInstrumentsLayout.createSequentialGroup()
                        .addGroup(pnlInstrumentsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                            .addGroup(pnlInstrumentsLayout.createSequentialGroup()
                                .addComponent(btnAddPart, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(btnReset, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                            .addGroup(pnlInstrumentsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 424, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addGroup(pnlInstrumentsLayout.createSequentialGroup()
                                    .addGroup(pnlInstrumentsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                        .addComponent(cmbInstrumentGroup, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE)
                                        .addComponent(jLabel3))
                                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                                    .addGroup(pnlInstrumentsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                        .addComponent(jLabel4)
                                        .addComponent(cmbInstrument, javax.swing.GroupLayout.PREFERRED_SIZE, 175, javax.swing.GroupLayout.PREFERRED_SIZE)))))
                        .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, pnlInstrumentsLayout.createSequentialGroup()
                        .addGap(0, 0, Short.MAX_VALUE)
                        .addGroup(pnlInstrumentsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                            .addComponent(btnChange)
                            .addGroup(pnlInstrumentsLayout.createSequentialGroup()
                                .addComponent(jLabel9)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                                .addComponent(sldVolume, javax.swing.GroupLayout.PREFERRED_SIZE, 206, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                                .addComponent(lblVolume, javax.swing.GroupLayout.PREFERRED_SIZE, 38, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(btnChangeVolume)))
                        .addGap(74, 74, 74))))
        );
        pnlInstrumentsLayout.setVerticalGroup(
            pnlInstrumentsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(pnlInstrumentsLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(pnlInstrumentsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(btnReset, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(btnAddPart, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 197, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(pnlInstrumentsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel3)
                    .addComponent(jLabel4))
                .addGap(8, 8, 8)
                .addGroup(pnlInstrumentsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(cmbInstrument, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(cmbInstrumentGroup, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(btnChange))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addGroup(pnlInstrumentsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(sldVolume, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addGroup(pnlInstrumentsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                        .addComponent(lblVolume, javax.swing.GroupLayout.PREFERRED_SIZE, 19, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addComponent(btnChangeVolume))
                    .addComponent(jLabel9))
                .addContainerGap())
        );

        lblTempo.setText("Tempo:");

        spTempo.setPreferredSize(new java.awt.Dimension(60, 23));
        spTempo.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                spTempoStateChanged(evt);
            }
        });

        lblInstrumentCount.setText("5");

        lblLength.setText("2:00");

        jLabel6.setText("Key:");

        cmbKey.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                cmbKeyActionPerformed(evt);
            }
        });

        spPopulation.setPreferredSize(new java.awt.Dimension(60, 23));
        spPopulation.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                spPopulationStateChanged(evt);
            }
        });

        lblTempo1.setText("Start Population:");

        jPanel1.setBorder(javax.swing.BorderFactory.createEtchedBorder());

        btnPlay.setIcon(new javax.swing.ImageIcon(getClass().getResource("/icons/play.png"))); // NOI18N
        btnPlay.setEnabled(false);
        btnPlay.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnPlayActionPerformed(evt);
            }
        });

        btnSave.setIcon(new javax.swing.ImageIcon(getClass().getResource("/icons/save.png"))); // NOI18N
        btnSave.setToolTipText("Save");
        btnSave.setEnabled(false);
        btnSave.setFocusable(false);
        btnSave.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        btnSave.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        btnSave.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnSaveActionPerformed(evt);
            }
        });

        btnStop.setIcon(new javax.swing.ImageIcon(getClass().getResource("/icons/stop.png"))); // NOI18N
        btnStop.setToolTipText("Stop");
        btnStop.setEnabled(false);
        btnStop.setFocusable(false);
        btnStop.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        btnStop.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        btnStop.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnStopActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(btnSave, javax.swing.GroupLayout.PREFERRED_SIZE, 31, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addComponent(btnPlay, javax.swing.GroupLayout.PREFERRED_SIZE, 32, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(btnStop, javax.swing.GroupLayout.PREFERRED_SIZE, 31, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap())
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addGap(2, 2, 2)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(btnStop)
                    .addComponent(btnPlay)
                    .addComponent(btnSave, javax.swing.GroupLayout.PREFERRED_SIZE, 31, javax.swing.GroupLayout.PREFERRED_SIZE)))
        );

        jLabel7.setText("Fitness:");

        sldFitness.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                sldFitnessStateChanged(evt);
            }
        });

        lblFitness.setText("50%");

        chkCrossover.setText("One Point Crossover");

        chkNPointCrossover.setText("N Point Crossover");

        chkMutation.setText("Mutation");

        jLabel8.setText("Type:");

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jLabel7)
                            .addComponent(jLabel8))
                        .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                        .addGap(0, 0, Short.MAX_VALUE)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                            .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                                .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
                                    .addComponent(lblTempo)
                                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                    .addComponent(spTempo, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                                .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
                                    .addComponent(lblTempo1)
                                    .addGap(35, 35, 35)
                                    .addComponent(spPopulation, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
                            .addComponent(pnlInstruments, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
                                .addComponent(jLabel6)
                                .addGap(45, 45, 45)
                                .addComponent(cmbKey, javax.swing.GroupLayout.PREFERRED_SIZE, 134, javax.swing.GroupLayout.PREFERRED_SIZE))
                            .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                                .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
                                    .addComponent(jLabel1)
                                    .addGap(18, 18, 18)
                                    .addComponent(cmbCategory, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                                .addGroup(layout.createSequentialGroup()
                                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                        .addComponent(jLabel2)
                                        .addComponent(jLabel5))
                                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                        .addGroup(layout.createSequentialGroup()
                                            .addComponent(sldInstrumentCount, javax.swing.GroupLayout.PREFERRED_SIZE, 360, javax.swing.GroupLayout.PREFERRED_SIZE)
                                            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                                            .addComponent(lblInstrumentCount, javax.swing.GroupLayout.PREFERRED_SIZE, 16, javax.swing.GroupLayout.PREFERRED_SIZE))
                                        .addGroup(layout.createSequentialGroup()
                                            .addGap(6, 6, 6)
                                            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                                .addComponent(chkCrossover)
                                                .addComponent(chkNPointCrossover)
                                                .addComponent(chkMutation)
                                                .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                                                    .addComponent(sldFitness, javax.swing.GroupLayout.PREFERRED_SIZE, 335, javax.swing.GroupLayout.PREFERRED_SIZE)
                                                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                                    .addComponent(lblFitness, javax.swing.GroupLayout.PREFERRED_SIZE, 38, javax.swing.GroupLayout.PREFERRED_SIZE))))
                                        .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                                            .addComponent(sldLength, javax.swing.GroupLayout.PREFERRED_SIZE, 341, javax.swing.GroupLayout.PREFERRED_SIZE)
                                            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                            .addComponent(lblLength, javax.swing.GroupLayout.PREFERRED_SIZE, 38, javax.swing.GroupLayout.PREFERRED_SIZE))))))
                        .addGap(14, 14, 14))))
            .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addComponent(btnCancel, javax.swing.GroupLayout.PREFERRED_SIZE, 69, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(10, 10, 10)
                .addComponent(btnCompose)
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel1)
                    .addComponent(cmbCategory, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addGap(19, 19, 19)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel6)
                    .addComponent(cmbKey, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addGap(18, 18, 18)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                    .addComponent(sldInstrumentCount, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(jLabel2)
                    .addComponent(lblInstrumentCount, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addGap(18, 18, 18)
                .addComponent(pnlInstruments, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(sldLength, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel5)
                    .addComponent(lblLength, javax.swing.GroupLayout.PREFERRED_SIZE, 19, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addGap(15, 15, 15)
                        .addComponent(lblTempo))
                    .addGroup(layout.createSequentialGroup()
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(spTempo, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(lblTempo1)
                    .addComponent(spPopulation, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(sldFitness, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel7)
                    .addComponent(lblFitness, javax.swing.GroupLayout.PREFERRED_SIZE, 19, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jLabel8)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(chkCrossover)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(chkNPointCrossover)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(chkMutation)))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(btnCompose)
                    .addComponent(btnCancel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addContainerGap())
        );

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

    /**
     * aktualisiert die Instrumente der ausgewaehlten Kategorie,
     * nachdem die Combobox aktualisiert wurde
     * @param evt 
     */
    private void cmbCategoryActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cmbCategoryActionPerformed
        fillInstrumentTable();
        fillKeys();
    }//GEN-LAST:event_cmbCategoryActionPerformed

    /**
     * schliesst den Dialog
     * @param evt 
     */
    private void btnCancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCancelActionPerformed
        try {
            MIDIPlayer.stop();
        }
        catch (NullPointerException npe) //Player wurde nie gespielt
        {
            //do nothing
        }
        dispose();
    }//GEN-LAST:event_btnCancelActionPerformed

    /**
     * beschraenkt den Wert zwischen 50 und 400
     * @param evt 
     */
    private void spTempoStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_spTempoStateChanged
        if ((int)spTempo.getValue() < 50){
            spTempo.setValue(50);
        } else if ((int)spTempo.getValue() > 400){
            spTempo.setValue(400);
        }
    }//GEN-LAST:event_spTempoStateChanged

    /**
     * aktualisiert das Label des Sliders mit dem aktuellen Wert
     * @param evt 
     */
    private void sldLengthStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_sldLengthStateChanged
        if (sldLength.getValue() > 59){
            int min = sldLength.getValue()/60;
            int sec = sldLength.getValue() - (min*60);
            if (sec < 10){
                lblLength.setText(min +":0" +sec);
            } else {
                lblLength.setText(min +":" +sec);
            }
        } else {
            lblLength.setText("0:" + sldLength.getValue());
        }
    }//GEN-LAST:event_sldLengthStateChanged

    /**
     * aktualisiert das Label des Sliders mit dem aktuellen Wert
     * @param evt 
     */
    private void sldInstrumentCountStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_sldInstrumentCountStateChanged
        lblInstrumentCount.setText("" + sldInstrumentCount.getValue());
        updateInstrumentTable();
    }//GEN-LAST:event_sldInstrumentCountStateChanged

    /**
     * 
     * @param evt 
     */
    private void btnComposeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnComposeActionPerformed
        //Instrumente auswerten
        btnPlay.setEnabled(false);
        btnStop.setEnabled(false);
        btnSave.setEnabled(false);
        btnCompose.setEnabled(false);
        Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    Compose();
                }
            });
            thread.start();
    }//GEN-LAST:event_btnComposeActionPerformed

    /**
     * erstellt eine neue Komposition
     */
    private void Compose(){
        csd = new ComposingStatusDialog(this, false);
        csd.setVisible(true);
        DefaultTableModel tableModel = (DefaultTableModel)tabInstruments.getModel();
        int rowCount = tableModel.getRowCount();
        int[] iInstruments = new int[rowCount];
        int[] iVolumes = new int[rowCount];
        for(int i = 0; i < rowCount; i++)
        {
            iInstruments[i] = getInstrumentIDForName(tableModel.getValueAt(i, 1).toString());
            iVolumes[i] = (int)tableModel.getValueAt(i, 2);
        }
        
        //genetischen Composer initialisieren
        pgc = new PolyphonGeneticComposer(categories.get(cmbCategory.getSelectedItem().toString()),
                (int)spTempo.getValue(),
                sldLength.getValue(),
                iInstruments,
                iVolumes,
                (int)spPopulation.getValue(),
                (double)sldFitness.getValue()/100.0,
                cmbKey.getSelectedItem().toString(),
                user,pw,url, csd, chkCrossover.isSelected(), chkNPointCrossover.isSelected(), chkMutation.isSelected());
        score = pgc.getComposition();
        csd.dispose();
        if (score == null){
            JOptionPane.showMessageDialog(this, "Not enough motifs for this instrument/instrumentgroup", "Error", JOptionPane.ERROR_MESSAGE);
        } else {
            btnPlay.setEnabled(true);
            btnStop.setEnabled(true);
            btnSave.setEnabled(true);
        }
        btnCompose.setEnabled(true);
    }
    
    /**
     * liefert zum uebergebenen Instrument(Instrumentengruppe) die passende ID
     * @param instrument Bezeichnung des Instruments/der Instrumentengruppe
     * @return ID des Instruments, 200 for Percussion and -1 if nothing found
     */
    private int getInstrumentIDForName(String instrument){
        //Instrumentengruppen durchsuchen
        AverageMIDIFileData amfd = new AverageMIDIFileData();
        if (amfd.getInstrumentGroup().containsKey(instrument)){
            return getInstrumentForGroup(instrument);
        } else { //keine Instrumentengruppe => Instrument
            MIDIInstrumentData mid = new MIDIInstrumentData();
            if (mid.getBasses().containsKey(instrument)){
                return mid.getBasses().get(instrument);
            } else if (mid.getBrasses().containsKey(instrument)){
                return mid.getBrasses().get(instrument);
            } else if (mid.getChromaticpercussion().containsKey(instrument)){
                return mid.getChromaticpercussion().get(instrument);
            } else if (mid.getEnsembles().containsKey(instrument)){
                return mid.getEnsembles().get(instrument);
            } else if (mid.getEthnics().containsKey(instrument)){
                return mid.getEthnics().get(instrument);
            } else if (mid.getGuitars().containsKey(instrument)){
                return mid.getGuitars().get(instrument);
            } else if (mid.getOrgans().containsKey(instrument)){
                return mid.getOrgans().get(instrument);
            } else if (mid.getPercussivs().containsKey(instrument)){
                return mid.getPercussivs().get(instrument);
            } else if (mid.getPianos().containsKey(instrument)){
                return mid.getPianos().get(instrument);
            } else if (mid.getPipes().containsKey(instrument)){
                return mid.getPipes().get(instrument);
            } else if (mid.getReeds().containsKey(instrument)){
                return mid.getReeds().get(instrument);
            } else if (mid.getSoundeffects().containsKey(instrument)){
                return mid.getSoundeffects().get(instrument);
            } else if (mid.getStrings().containsKey(instrument)){
                return mid.getStrings().get(instrument);
            } else if (mid.getSyntheffects().containsKey(instrument)){
                return mid.getSyntheffects().get(instrument);
            } else if (mid.getSynthleads().containsKey(instrument)){
                return mid.getSynthleads().get(instrument);
            } else if (mid.getSynthpads().containsKey(instrument)){
                return mid.getSynthpads().get(instrument);
            } else if (instrument.equalsIgnoreCase("Percussion")){
                return 200;
            } else { //nothing found
                return -1;
            }
        }
    }
    
    /**
    * gibt ein Instrument der Instrumentengruppe zurueck,
    * welches in dem Genre verwendet wurde
    * @param group Instrumentengruppe (MIDI)
    * @return Instrument der Gruppe des Genres
    */
    private int getInstrumentForGroup(String group){
       int from, to;
       
        switch (group) {
            case "Piano":
                from = 0;
                to = 7;
                break;
            case "Chromatic Percussion":
                from = 8;
                to = 15;
                break;
            case "Organ":
                from = 16;
                to = 23;
                break;
            case "Guitar":
                from = 24;
                to = 31;
                break;
            case "Bass":
                from = 32;
                to = 39;
                break;
            case "Strings":
                from = 40;
                to = 47;
                break;
            case "Ensemble":
                from = 48;
                to = 55;
                break;
            case "Brass":
                from = 56;
                to = 63;
                break;
            case "Reed":
                from = 64;
                to = 71;
                break;
            case "Pipe":
                from = 72;
                to = 79;
                break;
            case "Synth Lead":
                from = 80;
                to = 87;
                break;
            case "Synth Pad":
                from = 88;
                to = 95;
                break;
            case "Synth Effects":
                from = 96;
                to = 103;
                break;
            case "Ethnic":
                from = 104;
                to = 111;
                break;
            case "Percussive":
                from = 112;
                to = 119;
                break;
            case "Sound Effects":
                from = 120;
                to = 127;
                break;
            default:
                from = -1;
                to = -1;
                break;        
        }
        if (categories.containsKey(cmbCategory.getSelectedItem().toString())) {
             int cat = categories.get(cmbCategory.getSelectedItem().toString());
             //zufaelliges Instrument der Kategorie, dessen Instrument zwischen 'from' und 'to' liegt
             DatabaseInterface dbI = new DatabaseInterface(user, pw, url);
             int inst = dbI.getRandomInstrumentFromCategory(cat, from, to);
             dbI.closeConnection();
             if (inst == -1){ //wenn nichts gefunden, gib erstes Instrument der Gruppe zurueck
                 return from;
             } else {
                return inst;
             }
        }
        return -1;
    }
    
    /**
     * aktualisiert den Inhalt der Combobox mit den Instrumenten
     * @param evt 
     */
    private void cmbInstrumentGroupActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cmbInstrumentGroupActionPerformed
        updateInstrumentCombobox((String)cmbInstrumentGroup.getSelectedItem());
    }//GEN-LAST:event_cmbInstrumentGroupActionPerformed

    /**
     * aendert die Inhalte der Comboboxen der Instrumente
     * entsprechend der ausgewaehlten Zeile in der Tabelle
     * @param evt 
     */
    private void tabInstrumentsMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_tabInstrumentsMouseClicked
        cmbInstrumentGroup.setSelectedItem(tabInstruments.getValueAt(tabInstruments.getSelectedRow(), 0)+"");
        updateInstrumentCombobox(tabInstruments.getValueAt(tabInstruments.getSelectedRow(), 0)+"");
        sldVolume.setValue((int)tabInstruments.getValueAt(tabInstruments.getSelectedRow(), 2));
    }//GEN-LAST:event_tabInstrumentsMouseClicked

    /**
     * aendert das zu verwendente Instrument
     * @param evt 
     */
    private void btnChangeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnChangeActionPerformed
        if (tabInstruments.getSelectedRow() != -1){
            tabInstruments.setValueAt(cmbInstrument.getSelectedItem(), tabInstruments.getSelectedRow(), 1);
        } else {
            JOptionPane.showMessageDialog(this, "Please select an instrument first.", "Error", JOptionPane.ERROR_MESSAGE);
        }
    }//GEN-LAST:event_btnChangeActionPerformed

    /**
     * stellt die urspruenglichen Instrumentenzuordnung wieder her
     * @param evt 
     */
    private void btnResetActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnResetActionPerformed
        fillInstrumentTable();
    }//GEN-LAST:event_btnResetActionPerformed

    private void cmbKeyActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cmbKeyActionPerformed
    }//GEN-LAST:event_cmbKeyActionPerformed

    /**
     * spielt die Komposition ab bzw. stoppt diese
     * @param evt 
     */
    private void btnPlayActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnPlayActionPerformed
        if (score != null) {
            try {
                MIDIPlayer.stop();
            }
            catch (NullPointerException npe) //Player wurde nie gespielt
            {
                //do nothing
            }
            MIDIAnalyser analyser = new MIDIAnalyser();
            IScore is = analyser.analyseTask(score);
            MIDIPlayer.play(is);
        }
    }//GEN-LAST:event_btnPlayActionPerformed

    /**
     * beschraenkt den Wert zwischen 2 und 20
     * @param evt 
     */
    private void spPopulationStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_spPopulationStateChanged
        if ((int)spPopulation.getValue() < 2){
            spPopulation.setValue(2);
        } else if ((int)spPopulation.getValue() > 20){
            spPopulation.setValue(20);
        }
    }//GEN-LAST:event_spPopulationStateChanged

    private void formWindowClosing(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowClosing
        
    }//GEN-LAST:event_formWindowClosing

    private void btnAddPartActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnAddPartActionPerformed
        DefaultTableModel tableModel = (DefaultTableModel)tabInstruments.getModel();
        if (tableModel.getRowCount() < 10){
            if (tableModel.getValueAt(tableModel.getRowCount()-1, 1).toString().equalsIgnoreCase("Percussions")){
                tableModel.insertRow(tableModel.getRowCount()-2, new Object[]{"choose instrument","Piano"});
            } else {
                tableModel.addRow(new Object[]{"choose instrument","Piano"});
            }
        }
    }//GEN-LAST:event_btnAddPartActionPerformed

    /**
     * speichert das MIDI-File
     * @param evt 
     */
    private void btnSaveActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnSaveActionPerformed
        if (score != null){
            //SaveFileDialog
            JFileChooser fileChooser = new JFileChooser(AnalyserForm.path);
            fileChooser.setAcceptAllFileFilterUsed(false);
            fileChooser.setDialogTitle("Save composition");
            fileChooser.setFileFilter(new FileNameExtensionFilter("MIDI-File (*.mid)", "mid"));
            fileChooser.setSelectedFile(new File(AnalyserForm.path +"\\" +cmbCategory.getSelectedItem() +".mid"));

            int userSelection = fileChooser.showSaveDialog(this);

            if (userSelection == JFileChooser.APPROVE_OPTION) {
                File fileToSave = fileChooser.getSelectedFile();
                String filename = fileToSave.getAbsolutePath();
                if (!filename.endsWith(".mid")){
                    filename += ".mid";
                }
                Write.midi(score, filename);
            }
        }
    }//GEN-LAST:event_btnSaveActionPerformed

    /**
     * stoppt das Abspielen einer MIDI-Datei
     * @param evt 
     */
    private void btnStopActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnStopActionPerformed
        try {
            MIDIPlayer.stop();
        }
        catch (NullPointerException npe) //Player wurde nie gespielt
        {
            //do nothing
        }
    }//GEN-LAST:event_btnStopActionPerformed

    /**
     * aktualisiert das Label des Sliders mit dem aktuellen Wert
     * @param evt 
     */
    private void sldFitnessStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_sldFitnessStateChanged
        int i = sldFitness.getValue();
        i = (int)Math.round((100.0/sldFitness.getMaximum())*i);
        
        lblFitness.setText(i +"%");
    }//GEN-LAST:event_sldFitnessStateChanged

    private void sldVolumeStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_sldVolumeStateChanged
        lblVolume.setText(sldVolume.getValue()+"");
    }//GEN-LAST:event_sldVolumeStateChanged

    private void btnChangeVolumeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnChangeVolumeActionPerformed
        if (tabInstruments.getSelectedRow() != -1){
            tabInstruments.setValueAt(sldVolume.getValue(), tabInstruments.getSelectedRow(), 2);
        } else {
            JOptionPane.showMessageDialog(this, "Please select an instrument first.", "Error", JOptionPane.ERROR_MESSAGE);
        }
    }//GEN-LAST:event_btnChangeVolumeActionPerformed

    /**
     * @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(PolyphoneComposingDialog.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(PolyphoneComposingDialog.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(PolyphoneComposingDialog.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(PolyphoneComposingDialog.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /* Create and display the dialog */
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                PolyphoneComposingDialog dialog = new PolyphoneComposingDialog(new javax.swing.JFrame(), true, null, null, null, null);
                dialog.addWindowListener(new java.awt.event.WindowAdapter() {
                    @Override
                    public void windowClosing(java.awt.event.WindowEvent e) {
                        System.exit(0);
                    }
                });
                dialog.setVisible(true);
            }
        });
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton btnAddPart;
    private javax.swing.JButton btnCancel;
    private javax.swing.JButton btnChange;
    private javax.swing.JButton btnChangeVolume;
    private javax.swing.JButton btnCompose;
    private javax.swing.JButton btnPlay;
    private javax.swing.JButton btnReset;
    private javax.swing.JButton btnSave;
    private javax.swing.JButton btnStop;
    private javax.swing.JCheckBox chkCrossover;
    private javax.swing.JCheckBox chkMutation;
    private javax.swing.JCheckBox chkNPointCrossover;
    private javax.swing.JComboBox cmbCategory;
    private javax.swing.JComboBox cmbInstrument;
    private javax.swing.JComboBox cmbInstrumentGroup;
    private javax.swing.JComboBox cmbKey;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JLabel jLabel5;
    private javax.swing.JLabel jLabel6;
    private javax.swing.JLabel jLabel7;
    private javax.swing.JLabel jLabel8;
    private javax.swing.JLabel jLabel9;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JLabel lblFitness;
    private javax.swing.JLabel lblInstrumentCount;
    private javax.swing.JLabel lblLength;
    private javax.swing.JLabel lblTempo;
    private javax.swing.JLabel lblTempo1;
    private javax.swing.JLabel lblVolume;
    private javax.swing.JPanel pnlInstruments;
    private javax.swing.JSlider sldFitness;
    private javax.swing.JSlider sldInstrumentCount;
    private javax.swing.JSlider sldLength;
    private javax.swing.JSlider sldVolume;
    private javax.swing.JSpinner spPopulation;
    private javax.swing.JSpinner spTempo;
    private javax.swing.JTable tabInstruments;
    // End of variables declaration//GEN-END:variables
}
