package de.renew.minimap.command;

import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.io.PrintStream;
import java.lang.reflect.InvocationTargetException;
import javax.swing.AbstractAction;
import javax.swing.JMenuItem;

import bibliothek.gui.dock.common.DefaultSingleCDockable;

import CH.ifa.draw.DrawPlugin;
import CH.ifa.draw.application.MenuManager;
import CH.ifa.draw.util.Command;
import de.renew.minimap.component.MiniMapFrame;
import de.renew.plugin.command.CLCommand;
import de.renew.windowmanagement.Workbench;

/**
 * This command adds a {@link bibliothek.gui.dock.common.DefaultSingleCDockable} with a MiniMap.
 *
 * @author Christian Roeder
 */
public class ShowMiniMapCommand extends Command implements CLCommand {
    private static final org.apache.log4j.Logger LOGGER =
        org.apache.log4j.Logger.getLogger(ShowMiniMapCommand.class);

    /**
     * The name of this command that is displayed throughout the project
     */
    public static final String COMMAND_NAME = "Show MiniMap...";

    //Frame containing the MiniMapFrame.
    private DefaultSingleCDockable _frame;

    //a menu item for the windows menu.
    private JMenuItem _menuItem;
    private Workbench _workbench;

    /**
     * Instantiates a new show mini map command.
     *
     * @param workbench workbench to add the window to
     */
    public ShowMiniMapCommand(Workbench workbench) {
        super(COMMAND_NAME);
        this._workbench = workbench;
    }

    /**
     * {@link CH.ifa.draw.util.Command#execute()}
     */
    @Override
    public void execute() {
        showMiniMap();
    }

    /**
     * {@link de.renew.plugin.command.CLCommand#execute(java.lang.String[], java.io.PrintStream)}
     *
     * @param args      The command line that was typed by the user.
     * @param response  The <code>PrintStream</code> for user feedback.
     */
    @Override
    public void execute(final String[] args, final PrintStream response) {
        try {
            EventQueue.invokeAndWait(new Runnable() {
                @Override
                public void run() {
                    response.println("Show MiniMap.");
                    execute();
                }
            });
        } catch (InterruptedException e) {
            // unexpected, but harmless.
        } catch (InvocationTargetException e) {
            response.println("Exception while showing MiniMap: " + e.getTargetException());
            LOGGER.error(e.getTargetException().toString(), e);
        }
    }

    /**
     * Gets the arguments.
     *
     * @return the arguments
     * {@link de.renew.plugin.command.CLCommand#getArguments()}
     */
    @Override
    public String getArguments() {
        return null;
    }

    /**
     * {@link de.renew.plugin.command.CLCommand#getDescription()}
     *
     * @return the description of this command
     */
    @Override
    public String getDescription() {
        return "Opens a window where commands can be executed.";
    }

    /**
     * Adds an menu item for the MiniMap frame to the windows menu.
     */
    private void addMenuItemToWindowsMenu() {
        if (_menuItem != null) {
            return;
        }
        _menuItem = new JMenuItem(new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                bringToFront();
            }
        });
        _menuItem.setText(COMMAND_NAME);
        MenuManager.getInstance().getWindowsMenu().add(_menuItem);
    }

    /**
     * Bring the MiniMap frame to the front.
     */
    private void bringToFront() {
        _frame.setVisible(true);
        _frame.toFront();
    }

    /**
     * Close MiniMap frame.
     */
    private void closeMiniMapFrame() {
        removeMenuItemFromWindowsMenu();
        MiniMapFrame.destroyMiniMapFrame();
    }

    /**
     * Removes the menu item from the windows menu.
     */
    private void removeMenuItemFromWindowsMenu() {
        DrawPlugin.getCurrent().getMenuManager().getWindowsMenu().remove(_menuItem);
        _menuItem = null;
    }

    /**
     * Show MiniMap.
     */
    private void showMiniMap() {
        _frame = MiniMapFrame.getFrame(_workbench);
        _frame.setVisible(true);
        addMenuItemToWindowsMenu();
    }
}