/*
 * Copyright 2010-2021 Australian Signals Directorate
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package au.gov.asd.tac.constellation.plugins.arrangements.tree;

import au.gov.asd.tac.constellation.graph.Graph;
import au.gov.asd.tac.constellation.graph.GraphElementType;
import au.gov.asd.tac.constellation.graph.utilities.widgets.AttributeSelectionPanel;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import javax.swing.ComboBoxModel;
import javax.swing.event.ListDataListener;

/**
 * UI panel for the user to enter the MDS parameters
 *
 * @author algol
 */
public class MDSChoicePanel extends javax.swing.JPanel {

    public MDSChoicePanel() {
        initComponents();

        linkWeightsCombo.setModel(new LinkWeightsModel());

        final MDSChoiceParameters params = MDSChoiceParameters.getDefaultParameters();
        linkWeightsCombo.setSelectedItem(params.linkWeight);
        scaleSpinner.setValue(params.scale);
        iterationsSpinner.setValue(params.iterationsPerStageTrial);
        maxTrialsSpinner.setValue(params.maxTrialsPerStage);
        minTrialsSpinner.setValue(params.minTrialsPerStage);
        avoidOverlapCheck.setSelected(params.tryToAvoidOverlap);
        avoidanceCombo.setSelectedItem(Integer.toString(params.overlapAvoidance));
    }

    public void setGraph(final Graph graph) {
        Collection<GraphElementType> elementTypes = Collections.singleton(GraphElementType.VERTEX);
        Collection<String> dataTypes = Collections.singleton("float");
        attributeSelectionPanel.setGraph(graph, elementTypes, dataTypes, null);
    }

    public MDSChoiceParameters getParameters() {
        final LinkWeight linkWeight = (LinkWeight) linkWeightsCombo.getSelectedItem();
        final int weightAttribute = attributeSelectionPanel.getAttributeId();
        final float scale = ((Float) scaleSpinner.getValue());
        final int iterationsPerStageTrial = ((Integer) iterationsSpinner.getValue());
        final int maxTrialsPerStage = ((Integer) maxTrialsSpinner.getValue());
        final int minTrialsPerStage = ((Integer) minTrialsSpinner.getValue());
        final boolean avoidOverlap = avoidOverlapCheck.isSelected();
        final int overlapAvoidance = Integer.parseInt((String) avoidanceCombo.getSelectedItem());

        return new MDSChoiceParameters(linkWeight, weightAttribute, scale, iterationsPerStageTrial, maxTrialsPerStage, minTrialsPerStage, avoidOverlap, overlapAvoidance);
    }

    private final class LinkWeightsModel implements ComboBoxModel<LinkWeight> {

        private final ArrayList<LinkWeight> items;
        private int selectedItem;
        private final ArrayList<ListDataListener> listeners;

        public LinkWeightsModel() {
            items = new ArrayList<>(Arrays.asList(LinkWeight.values()));
            setSelectedItem(LinkWeight.defaultEnum());
            listeners = new ArrayList<>();
        }

        @Override
        public void setSelectedItem(final Object anItem) {
            final LinkWeight weight = (LinkWeight) anItem;
            for (int i = 0; i < items.size(); i++) {
                if (items.get(i) == weight) {
                    selectedItem = i;
                    return;
                }
            }

            selectedItem = 0;
        }

        @Override
        public Object getSelectedItem() {
            return items.get(selectedItem);
        }

        @Override
        public int getSize() {
            return items.size();
        }

        @Override
        public LinkWeight getElementAt(final int index) {
            return items.get(index);
        }

        @Override
        public void addListDataListener(final ListDataListener l) {
            listeners.add(l);
        }

        @Override
        public void removeListDataListener(final ListDataListener l) {
            listeners.remove(l);
        }

    }

    /**
     * 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();
        linkWeightsCombo = new javax.swing.JComboBox();
        attributeSelectionPanel = new AttributeSelectionPanel("Select a weight attribute");
        jLabel3 = new javax.swing.JLabel();
        jLabel4 = new javax.swing.JLabel();
        jLabel5 = new javax.swing.JLabel();
        jLabel6 = new javax.swing.JLabel();
        avoidOverlapCheck = new javax.swing.JCheckBox();
        jLabel7 = new javax.swing.JLabel();
        avoidanceCombo = new javax.swing.JComboBox();
        iterationsSpinner = new javax.swing.JSpinner();
        maxTrialsSpinner = new javax.swing.JSpinner();
        minTrialsSpinner = new javax.swing.JSpinner();
        scaleSpinner = new javax.swing.JSpinner();
        jSeparator1 = new javax.swing.JSeparator();

        jLabel1.setText(org.openide.util.NbBundle.getMessage(MDSChoicePanel.class, "MDSChoicePanel.jLabel1.text")); // NOI18N

        attributeSelectionPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(MDSChoicePanel.class, "MDSChoicePanel.attributeSelectionPanel.border.title"))); // NOI18N

        jLabel3.setText(org.openide.util.NbBundle.getMessage(MDSChoicePanel.class, "MDSChoicePanel.jLabel3.text")); // NOI18N

        jLabel4.setText(org.openide.util.NbBundle.getMessage(MDSChoicePanel.class, "MDSChoicePanel.jLabel4.text")); // NOI18N

        jLabel5.setText(org.openide.util.NbBundle.getMessage(MDSChoicePanel.class, "MDSChoicePanel.jLabel5.text")); // NOI18N

        jLabel6.setText(org.openide.util.NbBundle.getMessage(MDSChoicePanel.class, "MDSChoicePanel.jLabel6.text")); // NOI18N

        avoidOverlapCheck.setSelected(true);
        avoidOverlapCheck.setText(org.openide.util.NbBundle.getMessage(MDSChoicePanel.class, "MDSChoicePanel.avoidOverlapCheck.text")); // NOI18N

        jLabel7.setText(org.openide.util.NbBundle.getMessage(MDSChoicePanel.class, "MDSChoicePanel.jLabel7.text")); // NOI18N

        avoidanceCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "50", "75", "100", "125", "150", "200", "250" }));
        avoidanceCombo.setSelectedIndex(2);

        iterationsSpinner.setModel(new javax.swing.SpinnerNumberModel(Integer.valueOf(20), Integer.valueOf(1), null, Integer.valueOf(1)));

        maxTrialsSpinner.setModel(new javax.swing.SpinnerNumberModel(Integer.valueOf(8), Integer.valueOf(1), null, Integer.valueOf(1)));

        minTrialsSpinner.setModel(new javax.swing.SpinnerNumberModel(Integer.valueOf(1), Integer.valueOf(1), null, Integer.valueOf(1)));

        scaleSpinner.setModel(new javax.swing.SpinnerNumberModel(Float.valueOf(1.0f), Float.valueOf(0.1f), null, Float.valueOf(0.1f)));

        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()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(jLabel1)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(linkWeightsCombo, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                    .addComponent(attributeSelectionPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addGroup(layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                            .addGroup(layout.createSequentialGroup()
                                .addComponent(jLabel7)
                                .addGap(31, 31, 31)
                                .addComponent(avoidanceCombo, 0, 78, Short.MAX_VALUE))
                            .addGroup(layout.createSequentialGroup()
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                    .addComponent(jLabel4)
                                    .addComponent(jLabel5)
                                    .addComponent(jLabel6))
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                                    .addComponent(iterationsSpinner, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 78, Short.MAX_VALUE)
                                    .addComponent(maxTrialsSpinner)
                                    .addComponent(minTrialsSpinner)))
                            .addComponent(avoidOverlapCheck)
                            .addGroup(layout.createSequentialGroup()
                                .addComponent(jLabel3)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(scaleSpinner, javax.swing.GroupLayout.PREFERRED_SIZE, 78, javax.swing.GroupLayout.PREFERRED_SIZE)))
                        .addGap(0, 0, Short.MAX_VALUE))
                    .addComponent(jSeparator1))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel1)
                    .addComponent(linkWeightsCombo, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(attributeSelectionPanel, 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(jLabel3)
                    .addComponent(scaleSpinner, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addGap(4, 4, 4)
                .addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, 10, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(4, 4, 4)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel4)
                    .addComponent(iterationsSpinner, 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(jLabel5)
                    .addComponent(maxTrialsSpinner, 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(jLabel6)
                    .addComponent(minTrialsSpinner, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(avoidOverlapCheck)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel7)
                    .addComponent(avoidanceCombo, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
    }// </editor-fold>//GEN-END:initComponents
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private au.gov.asd.tac.constellation.graph.utilities.widgets.AttributeSelectionPanel attributeSelectionPanel;
    private javax.swing.JCheckBox avoidOverlapCheck;
    private javax.swing.JComboBox avoidanceCombo;
    private javax.swing.JSpinner iterationsSpinner;
    private javax.swing.JLabel jLabel1;
    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.JSeparator jSeparator1;
    private javax.swing.JComboBox linkWeightsCombo;
    private javax.swing.JSpinner maxTrialsSpinner;
    private javax.swing.JSpinner minTrialsSpinner;
    private javax.swing.JSpinner scaleSpinner;
    // End of variables declaration//GEN-END:variables
}
