package de.renew.windowmanagement;

import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JPanel;

import bibliothek.gui.dock.common.DefaultMultipleCDockable;
import bibliothek.gui.dock.common.DefaultSingleCDockable;
import bibliothek.gui.dock.common.MultipleCDockable;
import bibliothek.gui.dock.common.MultipleCDockableFactory;
import bibliothek.gui.dock.common.MultipleCDockableLayout;
import bibliothek.gui.dock.common.SingleCDockable;
import bibliothek.gui.dock.common.event.CControlListener;
import bibliothek.gui.dock.common.event.CFocusListener;
import bibliothek.gui.dock.common.event.CKeyboardListener;
import bibliothek.gui.dock.common.event.CVetoClosingListener;
import bibliothek.util.Path;

/**
 * This is the interface that provides different interactions methods for the two classes (WorkbenchImpl and WorkbenchProxy)
 * to interact with each other.
 */
public interface Workbench {

    /**
     * Returns the main frame of this application.
     * If you want to add new components, please use the methods {@link #addEditorWindow(MultipleCDockableLayout, String)}
     * {@link #addViewWindow(DefaultSingleCDockable, Path)} {@link #addStaticPanel(JPanel)} instead.
     *
     * @return the main frame
     */
    JFrame getMainFrame();

    /**
     * Display the given String on the status line.
     *
     * @param string that you want to show on the status line.
     */
    void showStatus(String string);

    /**
     * Add a panel to the upper tool bar.
     *
     * @param panel the panel you want to add to the tool bar.
     */
    void addStaticPanel(JPanel panel);

    /**
     * Add an editor window to the main frame.
     * Prior to calling this, a {@link MultipleCDockableFactory} has to be registered via the {@link #registerEditorFactory(MultipleCDockableFactory, String)} method.
     *
     * @param editor A {@link DefaultMultipleCDockable} compatible with an already registered factory.
     * @param factoryID the factory where you want to build it
     */
    void addEditorWindow(MultipleCDockableLayout editor, String factoryID);

    /**
     * A new editor will be created by the chosen factory.
     *
     * @param factoryID The ID of the {@link MultipleCDockableFactory} used to create the editor window.
     */
    void newEditorWindow(String factoryID);

    /**
     * Register a listener to the controller.
     * Whenever a window is opened, closed, added or removed, all listeners will be called.
     *
     * @param listener the listener you want register to the controller.
     */
    void registerControlListener(CControlListener listener);

    /**
     * Register a new factory to create {@link MultipleCDockable}.
     * The factory should have unique id.
     *
     * @param factory the factory you want register
     * @param id unique factory ID
     */
    void registerEditorFactory(MultipleCDockableFactory factory, String id);

    /**
     * Register a new menu to the upper menu bar.
     *
     * @param menu the menu that you want to register.
     */
    void registerMenu(JMenu menu);

    /**
     * Register a new menu to the upper menu bar at the specified index.
     *
     * @param menu the menu that you want to register.
     * @param index the index where you want to register the menu.
     * @throws UnknownMenuSectionException if the menu section is not found.
     */
    void registerMenu(JMenu menu, int index) throws UnknownMenuSectionException;

    /**
     * Remove a menu from the upper menu bar.
     *
     * @param menu the menu that has to be removed.
     */
    void removeMenu(JMenu menu);

    /**
     * Removes the specified window.
     *
     * @param dockable the windows that has to be removed.
     */
    void close(MultipleCDockable dockable);

    /**
     * Removes the specified window.
     *
     * @param dockable the window that has to be removed.
     */
    void close(SingleCDockable dockable);

    /**
     * Add a view window to the main frame.
     * Views are always one of a kind and need unique IDs.
     * If the specified path already contains a view, the new view will be put in a tab.
     * <p>
     * This class provides four paths as static fields, but other plugins might add more or different paths with different perspectives.
     *
     * @param dockable The window to be shown
     * @param path     Where on the main frame the window will be shown
     */
    void addViewWindow(DefaultSingleCDockable dockable, Path path);

    /**
     * Register a shutdown hook.
     * All hooks will be asked to agree to a closing of the mainframe.
     *
     * @param hook the hook that has to be registered.
     */
    void registerShutdownHook(RenewShutdownHook hook);

    /**
     * Renew can be started without a gui.
     * Use this method to activate the gui.
     */
    void openGui();

    /**
     * Adds a focus listener to the controller.
     * Whenever a window is focused or focus on a window is lost, calls all listeners.
     *
     * @param listener of type CFocusListener
     */
    void registerFocusListener(CFocusListener listener);

    /**
     * Adds a listener to the controller.
     * Whenever a window is closed, calls all listeners.
     * Listeners may prevent closing of the window.
     *
     * @param listener of type CVetoClosingListener
     */
    void registerVetoClosingListener(CVetoClosingListener listener);

    /**
     * Adds a listener to the controller.
     * {@link bibliothek.gui.dock.common.CControl#addKeyboardListener(CKeyboardListener)}
     *
     * @param listener of type CKeyboardListener
     */
    void registerKeyboardListener(CKeyboardListener listener);
}
