/**
 *  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.MouseEvent;
import java.awt.event.MouseListener;

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

import javax.swing.JPanel;

import net.sf.jaxodraw.gui.menu.popup.JaxoZoomPopupMenu;
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
 * grid button menu.
 * @since 2.0
 */
public class JaxoGridButtons extends JPanel implements MouseListener,
    PropertyChangeListener, JaxoLocalized {
    private static final long serialVersionUID = 7526471155622776147L;
    private static final String[] GRID_BUTTON_ICONS =
    {"snap.png", "viewmag1.png", "empty.png", "exit.png"};
    private static final int[] GRID_MODES =
    {
        JaxoConstants.GRID, JaxoConstants.ZOOM, JaxoConstants.DUMMIE,
        JaxoConstants.QUIT
    };
    private static final int NOF_BUTTONS = GRID_MODES.length;
    private static final String[] TOOLTIP_KEYS =
    {"Snap_points_to_the_grid", "Dynamical_zoom", "", "Exits_JaxoDraw"};
    private final JaxoPanelButton[] gridButtons =
        new JaxoPanelButton[NOF_BUTTONS];
    private final JaxoZoomPopupMenu zoomPopup;

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

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

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

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

        zoomPopup = new JaxoZoomPopupMenu();
        gridButtons[0].addMouseListener(this);
        gridButtons[1].addMouseListener(this);

        updateGrid(false);
        updateSnap(false);

        //Disable third button
        gridButtons[2].setEnabled(false);
    }

    /**
     * Applies a property change event.
     *
     * @param e the change event.
     */
    public void propertyChange(final PropertyChangeEvent e) {
        final String name = e.getPropertyName();

        if ("Jaxo.gridOn".equals(name)) {
            updateGrid(Boolean.TRUE.equals(e.getNewValue()));
        } else if ("Jaxo.snap".equals(name)) {
            updateSnap(Boolean.TRUE.equals(e.getNewValue()));
        }
    }

    /** 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++) {
            gridButtons[i].addActionListener(l);
        }
        zoomPopup.addActionListener(l);
    }

    private void updateGrid(final boolean on) {
        gridButtons[getIndex(JaxoConstants.GRID)].setEnabled(on);
    }

    private void updateSnap(final boolean on) {
        gridButtons[getIndex(JaxoConstants.GRID)].setSelected(on);
    }

    /** Sets the zoom button as not pressed. */
    private void unsetButtons() {
        // zoom is the only grid button that corresponds to an edit mode
        // the grid button keeps its state
        gridButtons[getIndex(JaxoConstants.ZOOM)].setSelected(false);
    }

    /** Returns the index of the particle button corresponding
     * to the grid event i.
     * @param i A grid event as defined in {@link JaxoConstants JaxoConstants}.
     * @return The index of the particle button corresponding
     * to the particle event i, or -1 if i is not a grid mode.
     */
    private int getIndex(final int i) {
        int j = -1;

        if (i == JaxoConstants.GRID) {
            j = 0;
        } else if (i == JaxoConstants.ZOOM) {
            j = 1;
        } else if (i == JaxoConstants.QUIT) {
            j = 3;
        }

        return j;
    }

    /** Set the button corresponding to mode as default.
     * If mode is not a grid 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.isGridMode(mode)) {
            final int j = getIndex(mode);
            gridButtons[j].setDefault(true);
        }
    }

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

    /** Sets the specified button as pressed.
     * If mode is not a grid 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.isGridMode(mode) && (mode != JaxoConstants.QUIT)) {
            final int j = getIndex(mode);
            gridButtons[j].setSelected(true);
        }
    }

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

        zoomPopup.updateLanguage();
    }

    /** Processes the right-click on the zoom button.
     * @param e The MouseEvent to be processed.
     */
    public final void mousePressed(final MouseEvent e) {
        if (JaxoUtils.isButton3(e) && (e.getComponent() == gridButtons[1])) {
            zoomPopup.show(e.getComponent(), e.getX(), e.getY());
        }
    }

    /** Does nothing.
     * @param e The MouseEvent to be processed.
     */
    public final void mouseClicked(final MouseEvent e) {
        // return;
    }

    /** Does nothing.
     * @param e The MouseEvent to be processed.
     */
    public final void mouseEntered(final MouseEvent e) {
        // return;
    }

    /** Does nothing.
     * @param e The MouseEvent to be processed.
     */
    public final void mouseExited(final MouseEvent e) {
        // return;
    }

    /** Does nothing.
     * @param e The MouseEvent to be processed.
     */
    public final void mouseReleased(final MouseEvent e) {
        // return;
    }
}
