package de.renew.formalism.gui;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Properties;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JMenuItem;

import CH.ifa.draw.standard.ConnectionTool;
import CH.ifa.draw.standard.ToolButton;
import CH.ifa.draw.util.Palette;
import de.renew.application.SimulatorPlugin;
import de.renew.draw.ui.ontology.DrawingEditor;
import de.renew.draw.ui.ontology.Tool;
import de.renew.gui.CPNApplication;
import de.renew.gui.GuiPlugin;
import de.renew.gui.HollowDoubleArcConnection;
import de.renew.gui.InhibitorConnection;
import de.renew.gui.PaletteHolder;
import de.renew.plugin.PluginManager;
import de.renew.plugin.PropertyHelper;
import de.renew.simulator.api.SimulatorPropertyConstants;


/**
 * This class is used when the Java Net Compiler is chosen.
 * <p>
 * It provides: <ul>
 * <li> a menu with an item to select the sequential compiler mode. </li>
 * <li> a palette with the inhibitor and clear arcs. This palette
 *      gets displayed only if the sequential compiler mode is
 *      activated. </li>
 * </ul>
 * @author J&ouml;rn Schumacher
 * @author Michael Duvigneau
 */
public class JavaGuiCreator implements FormalismGuiCreator {
    public static final org.apache.log4j.Logger LOGGER =
        org.apache.log4j.Logger.getLogger(JavaGuiCreator.class);

    private boolean _toolsVisible = false;
    private Palette _sequentialTools = null;
    private JCheckBoxMenuItem _sequentialItem;

    /*
     * @see de.renew.gui.FormalismPlugin.FormalismGuiCreator#createMenus()
     */
    @Override
    public JMenuItem createMenu() {
        int mult = PropertyHelper.getIntProperty(
            getSimulatorPlugin().getProperties(), SimulatorPropertyConstants.MODE_PROP_NAME, 1);
        boolean isSequential = (mult == -1);
        _sequentialItem = new JCheckBoxMenuItem("Show sequential-only arcs", isSequential);
        _sequentialItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                sequentialChanged();
            }
        });
        sequentialChanged();
        return _sequentialItem;
    }

    @Override
    public Palette createPalette() {
        return null;
    }

    @Override
    public void formalismActivated() {
        // nothing to do.
    }

    @Override
    public void formalismDeactivated() {
        hideSequentialPalette();
    }

    private void sequentialChanged() {
        // TODO: React to direct property changes (if someone
        // configures the simulation engine from outside)
        boolean isSequential = _sequentialItem.isSelected();
        if (isSequential) {
            createSequentialPalette();
        } else {
            hideSequentialPalette();
        }
    }

    private void hideSequentialPalette() {
        if ((_sequentialTools != null) && _toolsVisible) {
            GuiPlugin guiPlugin = GuiPlugin.getCurrent();
            guiPlugin.getPaletteHolder().removePalette(_sequentialTools);
            _toolsVisible = false;
        }
    }

    private void createSequentialPalette() {
        GuiPlugin guiPlugin = GuiPlugin.getCurrent();
        PaletteHolder paletteHolder = guiPlugin.getPaletteHolder();
        if (_sequentialTools == null) {
            guiPlugin.openGui(); // open GUI to initialise the drawing editor
            DrawingEditor editor = guiPlugin.getDrawingEditor();
            Tool tool = new ConnectionTool(editor, InhibitorConnection.InhibitorArc);
            _sequentialTools = new Palette("net elements for sequential mode");
            ToolButton button = paletteHolder
                .createToolButton(CPNApplication.CPNIMAGES + "INHIB", "InhibitorArc Tool", tool);
            _sequentialTools.add(button);

            tool = new ConnectionTool(editor, HollowDoubleArcConnection.HollowArc);
            button = paletteHolder
                .createToolButton(CPNApplication.CPNIMAGES + "DHARC", "ClearArc Tool", tool);
            _sequentialTools.add(button);
        }
        if (!_toolsVisible) {
            Properties props = getSimulatorPlugin().getProperties();
            if (!props.getProperty(SimulatorPropertyConstants.MODE_PROP_NAME, "").trim()
                .equals("-1")) {
                props.setProperty(SimulatorPropertyConstants.MODE_PROP_NAME, "-1");
                if (LOGGER.isInfoEnabled()) {
                    LOGGER.info(
                        "For your convenience, the sequential simulation mode has been turned on, too.");
                    LOGGER.info(
                        "In order to reset your simulation to concurrent simulation mode do: set "
                            + SimulatorPropertyConstants.MODE_PROP_NAME + "=1");
                    LOGGER.info("or uncheck the propterty in the \"Configure Simulation\" dialog.");
                }
            }

            paletteHolder.addPalette(_sequentialTools);
            _toolsVisible = true;
        }
    }

    private SimulatorPlugin getSimulatorPlugin() {
        return (SimulatorPlugin) PluginManager.getInstance()
            .getPluginsProviding("de.renew.simulator").iterator().next();
    }

    /**
     * Returns a gui creator suitable for sequential-only formalisms. This
     * gui creator will always display the palette with sequential tools.
     **/
    public FormalismGuiCreator getSequentialJavaGuiCreator() {
        return new SequentialJavaGuiCreator();
    }

    private class SequentialJavaGuiCreator implements FormalismGuiCreator {
        @Override
        public JMenuItem createMenu() {
            return null;
        }

        @Override
        public Palette createPalette() {
            return null;
        }

        @Override
        public void formalismActivated() {
            createSequentialPalette();
        }

        @Override
        public void formalismDeactivated() {
            hideSequentialPalette();
        }
    }
}
