package de.renew.gui.nin;

import java.awt.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.swing.*;
import javax.swing.border.TitledBorder;

public class CustomCompositionPanel {

    /**
     * Create a dialog to add a custom composition
     *
     * @param parent add dialog to this panel
     * @param title give the dialog this title
     * @param channelNames consider each channel
     * @param size consider this many net instances
     * @return {@link JOptionPane#OK_OPTION}
     */
    public static Map<String, Map<String, FormattedNumberTextField>> showConfirmDialog(
        JPanel parent, String title, Set<String> channelNames, int size)
    {
        Map<String, Map<String, FormattedNumberTextField>> compSelectionMap = new HashMap<>();

        JPanel container = new JPanel();
        container.setLayout(new GridLayout());

        List<String> channelList = new ArrayList<>(channelNames);
        for (int i = 0; i < size; i++) {
            JPanel channelContainer = new JPanel();
            channelContainer.setLayout(new BoxLayout(channelContainer, BoxLayout.Y_AXIS));
            String netName = "net" + i;
            channelContainer.setBorder(new TitledBorder(netName));

            Map<String, FormattedNumberTextField> channelNumberMap = new HashMap<>();
            for (String channel : channelList) {
                JPanel elementContainer = new JPanel();
                elementContainer.setLayout(new GridLayout());

                DefaultListModel<String> model = new DefaultListModel<>();
                JList<String> list = new JList<>(model);
                model.addElement(channel);

                elementContainer.add(list);

                elementContainer.add(buildCountPanel(channel, channelNumberMap));

                channelContainer.add(elementContainer);
            }
            compSelectionMap.put(netName, channelNumberMap);
            container.add(channelContainer);
        }

        JScrollPane scrollPane = new JScrollPane(container);
        int height = channelNames.size() < 4 ? 80 * channelNames.size() : 200;
        scrollPane.setPreferredSize(new Dimension(600, height));
        JOptionPane.showConfirmDialog(parent, scrollPane, title, JOptionPane.DEFAULT_OPTION);
        return compSelectionMap;
    }

    /**
     * Build a panel for the instance number and
     * plus/minus buttons for a channel.
     * Add the numberfield to the number map
     * in order to retrieve its value later.
     *
     * @return the constructed panel
     * @param channel put this channel into the map
     * @param channelNumberMap put the new text field into the map with its channel
     */
    private static JPanel buildCountPanel(
        String channel, Map<String, FormattedNumberTextField> channelNumberMap)
    {
        JPanel countpanel = new JPanel();
        FormattedNumberTextField numberfield = new FormattedNumberTextField(0);

        countpanel.setLayout(new GridLayout());
        JButton plusbutton = new JButton("+");
        JButton minusbutton = new JButton("-");
        addPlusMinusActions(plusbutton, minusbutton, numberfield);

        countpanel.add(plusbutton);
        countpanel.add(numberfield);
        countpanel.add(minusbutton);
        channelNumberMap.put(channel, numberfield);
        return countpanel;
    }

    /**
     * Add an action response to plus and minus buttons.
     *
     * @param plusbutton add an action listener for incrementing
     * @param minusbutton add an action listener for decrementing
     * @param numberfield change this textfield
     */
    private static void addPlusMinusActions(
        JButton plusbutton, JButton minusbutton, FormattedNumberTextField numberfield)
    {
        plusbutton.addActionListener(e -> {
            int instanceCount = (Integer) numberfield.getValue();
            instanceCount++;
            if (instanceCount >= 0 && instanceCount < Integer.MAX_VALUE) {
                numberfield.setValue(instanceCount);
            }
        });
        minusbutton.addActionListener(e -> {
            int instanceCount = (Integer) numberfield.getValue();
            instanceCount--;
            if (instanceCount >= 0 && instanceCount < Integer.MAX_VALUE) {
                numberfield.setValue(instanceCount);
            }
        });
    }
}
