/**
 *  Licensed under GPL. For more information, see
 *    http://jaxodraw.sourceforge.net/license.html
 *  or the LICENSE file in the jaxodraw distribution.
 */
package net.sf.jaxodraw.gui.panel.button;

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import javax.swing.ImageIcon;
import javax.swing.JPanel;

import net.sf.jaxodraw.gui.menu.popup.JaxoVertexPopupMenu;
import net.sf.jaxodraw.util.JaxoConstants;
import net.sf.jaxodraw.util.JaxoLanguage;
import net.sf.jaxodraw.util.JaxoLocalized;
import net.sf.jaxodraw.util.JaxoUtils;


/** Responsible for displaying and modifying the buttons of the
 * misc button menu.
 * @since 2.0
 */
public class JaxoMiscButtons extends JPanel
        implements PropertyChangeListener, JaxoLocalized {
    private static final long serialVersionUID = 7526471155622776147L;
    private static final String[] MISC_BUTTON_ICONS =
    {
        "zigzag.png", "box.png", "blob.png", "vertexT1.png",
        "font_truetype.png", "latex.png", "empty.png", "empty.png"
    };
    private static final String[] VERTEX_BUTTON_ICONS =
    {
        "vertexT1.png", "vertexT2.png", "vertexT3.png", "vertexT4.png",
        "vertexT5.png", "vertexT6.png"
    };
    private static final int[] MISC_MODES =
    {
        JaxoConstants.ZIGZAG, JaxoConstants.BOX, JaxoConstants.BLOB,
        JaxoConstants.VERTEX, JaxoConstants.TEXT, JaxoConstants.LATEX,
        JaxoConstants.DUMMIE, JaxoConstants.DUMMIE
    };
    private static final int NOF_BUTTONS = MISC_MODES.length;
    private static final int VERTEX_BUTTON = 3;
    private static final String[] TOOLTIP_KEYS =
    {
        "Draw_a_zigzag_line", "Draw_a_box", "Draw_a_blob", "Draw_a_vertex",
        "Draw_a_text_string", "Draw_a_LaTex_text", "", ""
    };
    private final JaxoVertexPopupMenu vertexPopup;

    /** An array holding the JaxoPanelButtons of the misc button panel. */
    private final JaxoPanelButton[] miscButtons = new JaxoPanelButton[NOF_BUTTONS];

    /** Constructor: lays out the misc button panel. */
    public JaxoMiscButtons() {
        super(new GridBagLayout());

        for (int i = 0; i < NOF_BUTTONS; i++) {
            miscButtons[i] = new JaxoPanelButton();
            miscButtons[i].setIcon(JaxoUtils.newImageIcon(MISC_BUTTON_ICONS[i]));
            miscButtons[i].setToolTipText(JaxoLanguage.translate(TOOLTIP_KEYS[i]));
            miscButtons[i].setId(JaxoConstants.getModeAsString(MISC_MODES[i]));
        }

        final GridBagConstraints c =
            (GridBagConstraints) JaxoButtonPanel.BUTTON_CONSTRAINTS.clone();

        for (int y = 0; y < 2; y++) {
            for (int x = 0; x < 4; x++) {
                c.gridx = x;
                c.gridy = y;
                add(miscButtons[x + (4 * y)], c);
            }
        }

        vertexPopup = new JaxoVertexPopupMenu();
        miscButtons[VERTEX_BUTTON].setIcon(getImageIcon(JaxoConstants.VERTEXT1));
        miscButtons[VERTEX_BUTTON].addMouseListener(new MouseAdapter() {
            @Override
            public final void mousePressed(final MouseEvent e) {
                if (JaxoUtils.isButton3(e)) {
                    vertexPopup.show(e.getComponent(), e.getX(), e.getY());
                }
            }
        });

        //Disable unused buttons
        miscButtons[6].setEnabled(false);
        miscButtons[7].setEnabled(false);
    }

    /**
     * Applies a property change event.
     *
     * @param e the change event.
     */
    public void propertyChange(final PropertyChangeEvent e) {
        // button panel only adds Jaxo.vertexType property
        updateVertexType(((Integer) e.getNewValue()).intValue());
    }

    /** Adds the given ActionListener to all buttons in this panel.
     * @param l The ActionListener to add.
     */
    public final void addActionListener(final ActionListener l) {
        for (int i = 0; i < NOF_BUTTONS; i++) {
            miscButtons[i].addActionListener(l);
        }
        vertexPopup.addActionListener(l);
    }

    /** Sets all the buttons as not pressed. */
    private void unsetButtons() {
        for (int i = 0; i < NOF_BUTTONS; i++) {
            miscButtons[i].setSelected(false);
        }
    }

    /** Returns the index of the misc button corresponding to the misc event i.
     * @param i A misc event as defined in {@link JaxoConstants JaxoConstants}.
     * @return The index of the misc button corresponding to the misc event i.
     */
    private int getIndex(final int i) {
        int j = NOF_BUTTONS + 1;

        for (int jj = 0; jj < NOF_BUTTONS; jj++) {
            if (i == MISC_MODES[jj]) {
                j = jj;
            }
        }

        return j;
    }

    /**
     * Sets the specified button as pressed.
     * If mode is not a misc mode or a vertex mode, all buttons are set as not pressed.
     *
     * @param mode The mode specifying the button to be pressed,
     * as defined in {@link JaxoConstants JaxoConstants}.
     */
    public final void pressButton(final int mode) {
        unsetButtons();
        if (JaxoConstants.isMiscMode(mode)) {
            final int j = getIndex(mode);
            miscButtons[j].setSelected(true);
        } else if (JaxoConstants.isVertexMode(mode)) {
            miscButtons[VERTEX_BUTTON].setSelected(true);
        }
    }

    /** Set the button corresponding to mode as default.
     * If mode is not a misc mode, all buttons are set as not default.
     * @param mode The button to set as default.
     */
    public final void setDefault(final int mode) {
        resetDefault();
        if (JaxoConstants.isMiscMode(mode)) {
            final int j = getIndex(mode);
            miscButtons[j].setDefault(true);
        }
    }

    /** Reset default to false for all buttons. */
    private void resetDefault() {
        for (int i = 0; i < NOF_BUTTONS; i++) {
            miscButtons[i].setDefault(false);
        }
    }

    /** {@inheritDoc} */
    public final void updateLanguage() {
        for (int i = 0; i < NOF_BUTTONS; i++) {
            miscButtons[i].setToolTipText(JaxoLanguage.translate(
                    TOOLTIP_KEYS[i]));
        }

        vertexPopup.updateLanguage();
    }

    /** Notification on change of vertex type.
        Updates the vertex button and the popup menu.
        Todo: Also selects vertex drawing mode (really always desired?)
     * @param value The vertex mode as defined in  {@link JaxoConstants}.
     */
    private void updateVertexType(final int value) {
        miscButtons[VERTEX_BUTTON].setIcon(getImageIcon(value));
        miscButtons[VERTEX_BUTTON].doClick(0);
        vertexPopup.updateVertexType(value);
    }

    private ImageIcon getImageIcon(final int mode) {
        return JaxoUtils.newImageIcon(VERTEX_BUTTON_ICONS[getVertexIndex(mode)]);
    }

    private int getVertexIndex(final int mode) {
        int index = -1;
        switch (mode) {
            case JaxoConstants.VERTEXT1:
                index = 0;
                break;
            case JaxoConstants.VERTEXT2:
                index = 1;
                break;
            case JaxoConstants.VERTEXT3:
                index = 2;
                break;
            case JaxoConstants.VERTEXT4:
                index = 3;
                break;
            case JaxoConstants.VERTEXT5:
                index = 4;
                break;
            case JaxoConstants.VERTEXT6:
                index = 5;
                break;
            default:
                break;
        }
        return index;
    }
}
