/*
 * ProGuard -- shrinking, optimization, obfuscation, and preverification
 *             of Java bytecode.
 *
 * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu)
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation; either version 2 of the License, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */
package proguard.gui;

import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.util.List;

/**
 * This <code>Jpanel</code> allows the user to move and remove entries in a
 * list and between lists. Extensions of this class should add buttons to add
 * and possibly edit entries, and to set and get the resulting list.
 *
 * @author Eric Lafortune
 */
abstract class ListPanel extends JPanel
{
    protected final DefaultListModel listModel = new DefaultListModel();
    protected final JList            list      = new JList(listModel);

    protected int firstSelectionButton = 2;


    protected ListPanel()
    {
        GridBagLayout layout = new GridBagLayout();
        setLayout(layout);

        GridBagConstraints listConstraints = new GridBagConstraints();
        listConstraints.gridheight = GridBagConstraints.REMAINDER;
        listConstraints.fill       = GridBagConstraints.BOTH;
        listConstraints.weightx    = 1.0;
        listConstraints.weighty    = 1.0;
        listConstraints.anchor     = GridBagConstraints.NORTHWEST;
        listConstraints.insets     = new Insets(0, 2, 0, 2);

        // Make sure some buttons are disabled or enabled depending on whether
        // the selection is empty or not.
        list.addListSelectionListener(new ListSelectionListener()
        {
            public void valueChanged(ListSelectionEvent e)
            {
                enableSelectionButtons();
            }
        });

        add(new JScrollPane(list), listConstraints);

        // something like the following calls are up to the extending class:
        //addAddButton();
        //addEditButton();
        //addRemoveButton();
        //addUpButton();
        //addDownButton();
        //
        //enableSelectionButtons();
    }


    protected void addRemoveButton()
    {
        JButton removeButton = new JButton(msg("remove"));
        removeButton.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent e)
            {
                // Remove the selected elements.
                removeElementsAt(list.getSelectedIndices());
            }
        });

        addButton(tip(removeButton, "removeTip"));
    }


    protected void addUpButton()
    {
        JButton upButton = new JButton(msg("moveUp"));
        upButton.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent e)
            {
                int[] selectedIndices = list.getSelectedIndices();
                if (selectedIndices.length > 0 &&
                    selectedIndices[0] > 0)
                {
                    // Move the selected elements up.
                    moveElementsAt(selectedIndices, -1);
                }
            }
        });

        addButton(tip(upButton, "moveUpTip"));
    }


    protected void addDownButton()
    {
        JButton downButton = new JButton(msg("moveDown"));
        downButton.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent e)
            {
                int[] selectedIndices = list.getSelectedIndices();
                if (selectedIndices.length > 0 &&
                    selectedIndices[selectedIndices.length-1] < listModel.getSize()-1)
                {
                    // Move the selected elements down.
                    moveElementsAt(selectedIndices, 1);
                }
            }
        });

        addButton(tip(downButton, "moveDownTip"));
    }


    /**
     * Adds a button that allows to copy or move entries to another ListPanel.
     *
     * @param buttonTextKey the button text key.
     * @param tipKey        the tool tip key.
     * @param panel         the other ListPanel.
     */
    public void addCopyToPanelButton(String          buttonTextKey,
                                     String          tipKey,
                                     final ListPanel panel)
    {
        JButton moveButton = new JButton(msg(buttonTextKey));
        moveButton.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent e)
            {
                int[]    selectedIndices  = list.getSelectedIndices();
                Object[] selectedElements = list.getSelectedValues();

                // Remove the selected elements from this panel.
                removeElementsAt(selectedIndices);

                // Add the elements to the other panel.
                panel.addElements(selectedElements);
            }
        });

        addButton(tip(moveButton, tipKey));
    }


    protected void addButton(JComponent button)
    {
        GridBagConstraints buttonConstraints = new GridBagConstraints();
        buttonConstraints.gridwidth = GridBagConstraints.REMAINDER;
        buttonConstraints.fill      = GridBagConstraints.HORIZONTAL;
        buttonConstraints.anchor    = GridBagConstraints.NORTHWEST;
        buttonConstraints.insets    = new Insets(0, 2, 0, 2);

        add(button, buttonConstraints);
    }


    /**
     * Returns a list of all right-hand side buttons.
     */
    public List getButtons()
    {
        List list = new ArrayList(getComponentCount()-1);

        // Add all buttons.
        for (int index = 1; index < getComponentCount(); index++)
        {
            list.add(getComponent(index));
        }

        return list;
    }


    protected void addElement(Object element)
    {
        listModel.addElement(element);

        // Make sure it is selected.
        list.setSelectedIndex(listModel.size() - 1);
    }


    protected void addElements(Object[] elements)
    {
        // Add the elements one by one.
        for (int index = 0; index < elements.length; index++)
        {
            listModel.addElement(elements[index]);
        }

        // Make sure they are selected.
        int[] selectedIndices = new int[elements.length];
        for (int index = 0; index < selectedIndices.length; index++)
        {
            selectedIndices[index] =
                listModel.size() - selectedIndices.length + index;
        }
        list.setSelectedIndices(selectedIndices);
    }


    protected void moveElementsAt(int[] indices, int offset)
    {
        // Remember the selected elements.
        Object[] selectedElements = list.getSelectedValues();

        // Remove the selected elements.
        removeElementsAt(indices);

        // Update the element indices.
        for (int index = 0; index < indices.length; index++)
        {
            indices[index] += offset;
        }

        // Reinsert the selected elements.
        insertElementsAt(selectedElements, indices);
    }


    protected void insertElementsAt(Object[] elements, int[] indices)
    {
        for (int index = 0; index < elements.length; index++)
        {
            listModel.insertElementAt(elements[index], indices[index]);
        }

        // Make sure they are selected.
        list.setSelectedIndices(indices);
    }


    protected void setElementAt(Object element, int index)
    {
        listModel.setElementAt(element, index);

        // Make sure it is selected.
        list.setSelectedIndex(index);
    }


    protected void setElementsAt(Object[] elements, int[] indices)
    {
        for (int index = 0; index < elements.length; index++)
        {
            listModel.setElementAt(elements[index], indices[index]);
        }

        // Make sure they are selected.
        list.setSelectedIndices(indices);
    }


    protected void removeElementsAt(int[] indices)
    {
        for (int index = indices.length - 1; index >= 0; index--)
        {
            listModel.removeElementAt(indices[index]);
        }

        // Make sure nothing is selected.
        list.clearSelection();

        // Make sure the selection buttons are properly enabled,
        // since the above method doesn't seem to notify the listener.
        enableSelectionButtons();
    }


    protected void removeAllElements()
    {
        listModel.removeAllElements();

        // Make sure the selection buttons are properly enabled,
        // since the above method doesn't seem to notify the listener.
        enableSelectionButtons();
    }


    /**
     * Enables or disables the buttons that depend on a selection.
     */
    protected void enableSelectionButtons()
    {
        boolean selected = !list.isSelectionEmpty();

        // Loop over all components, except the list itself and the Add button.
        for (int index = firstSelectionButton; index < getComponentCount(); index++)
        {
            getComponent(index).setEnabled(selected);
        }
    }


    /**
     * Attaches the tool tip from the GUI resources that corresponds to the
     * given key, to the given component.
     */
    private static JComponent tip(JComponent component, String messageKey)
    {
        component.setToolTipText(msg(messageKey));

        return component;
    }


    /**
     * Returns the message from the GUI resources that corresponds to the given
     * key.
     */
    private static String msg(String messageKey)
    {
         return GUIResources.getMessage(messageKey);
    }
}
