/*
 * Copyright (C) 2004 NNL Technology AB
 * Visit www.infonode.net for information about InfoNode(R) 
 * products and how to contact NNL Technology AB.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, 
 * MA 02111-1307, USA.
 */

/* I18N par FaVdB 2016 */


// $Id: WindowMenuUtil.java,v 1.27 2007/01/28 21:25:10 jesper Exp $
package api.infonode.docking.util;

import api.infonode.docking.*;
import api.infonode.docking.action.*;
import api.infonode.docking.internalutil.InternalDockingUtil;
import api.infonode.gui.icon.button.ArrowIcon;
import api.infonode.gui.menu.MenuUtil;
import api.infonode.tabbedpanel.TabbedPanelProperties;
import api.infonode.tabbedpanel.titledtab.TitledTabProperties;
import api.infonode.util.Direction;

import javax.swing.*;
import java.awt.event.ActionEvent;

import i18n.I18N;

/**
 * Class containing utility methods for creating window popup menues.
 *
 * @author $Author: jesper $
 * @version $Revision: 1.27 $
 */
public final class WindowMenuUtil {
  private WindowMenuUtil() {
  }

  private static final Icon[] ARROW_ICONS = new Icon[4];

  static {
    final Direction[] directions = Direction.getDirections();

    for (int i = 0; i < directions.length; i++)
      ARROW_ICONS[i] = new ArrowIcon(InternalDockingUtil.DEFAULT_BUTTON_ICON_SIZE + 1, directions[i]);
  }

  private static AbstractTabWindow getTabWindowFor(DockingWindow window) {
    return (AbstractTabWindow)
        (window instanceof AbstractTabWindow ? window :
         window.getWindowParent() != null && window.getWindowParent() instanceof AbstractTabWindow ?
         window.getWindowParent() :
         null);
  }

  private static JMenu getMoveToMenuItems(final DockingWindow window) {
    JMenu moveToMenu = new JMenu(I18N.getMsg("infonode.move"));

    if (window.isMinimizable()) {
      final RootWindow root = window.getRootWindow();
      final Direction[] directions = Direction.getDirections();

      for (int i = 0; i < 4; i++) {
        final Direction dir = directions[i];

        if (!DockingUtil.isAncestor(root.getWindowBar(dir), window) && root.getWindowBar(dir).isEnabled()) {
          moveToMenu.add(new JMenuItem(dir.getName(), ARROW_ICONS[i])).addActionListener((ActionEvent e) -> {
			  root.getWindowBar(dir).addTab(window);
		  });
        }
      }
    }

    return moveToMenu;
  }

  private static void addWindowMenuItems(JPopupMenu menu, DockingWindow window) {
    menu.add(UndockWithAbortWindowAction.INSTANCE.getAction(window).toSwingAction());
    menu.add(DockWithAbortWindowAction.INSTANCE.getAction(window).toSwingAction());
    menu.add(RestoreWithAbortWindowAction.INSTANCE.getAction(window).toSwingAction());
    menu.add(MinimizeWithAbortWindowAction.INSTANCE.getAction(window).toSwingAction());

    if (window instanceof TabWindow)
      menu.add(MaximizeWithAbortWindowAction.INSTANCE.getAction(window).toSwingAction());

    menu.add(CloseWithAbortWindowAction.INSTANCE.getAction(window).toSwingAction());

    if (window.getWindowParent() instanceof AbstractTabWindow)
      menu.add(CloseOthersWindowAction.INSTANCE.getAction(window).toSwingAction());

    JMenu moveToMenu = getMoveToMenuItems(window);

    if (moveToMenu.getItemCount() > 0) {
      menu.add(moveToMenu);
    }
  }

  private static void addNewViewMenuItems(JPopupMenu menu, final DockingWindow window, ViewFactoryManager viewManager) {
    ViewFactory[] viewFactories = viewManager.getViewFactories();

    if (viewFactories.length == 0)
      return;

    JMenu viewsPopup = new JMenu(I18N.getMsg("infonode.show"));

	  for (ViewFactory vf : viewFactories) {
		  viewsPopup.add(new JMenuItem(vf.getTitle(), vf.getIcon())).addActionListener((ActionEvent e) -> {
			  View view = vf.createView();
			  
			  if (view.getRootWindow() == window.getRootWindow())
				  return;
			  
			  view.restore();
			  
			  if (view.getRootWindow() == window.getRootWindow())
				  return;
			  
			  if (window instanceof RootWindow)
				  ((RootWindow) window).setWindow(view);
			  else {
				  AbstractTabWindow tabWindow = getTabWindowFor(window);
				  
				  if (tabWindow != null)
					  tabWindow.addTab(view);
			  }
		  });
	  }

    menu.add(viewsPopup);
  }

  private static void addTabOrientationMenuItems(JPopupMenu menu, DockingWindow window) {
    final AbstractTabWindow tabWindow = getTabWindowFor(window);

    if (tabWindow == null || tabWindow instanceof WindowBar)
      return;

    JMenu orientationMenu = new JMenu(I18N.getMsg("infonode.orientation"));
    TabbedPanelProperties properties = tabWindow.getTabWindowProperties().getTabbedPanelProperties();
    final Direction[] directions = Direction.getDirections();

    for (int i = 0; i < directions.length; i++) {
      final Direction dir = directions[i];
      JMenuItem item = orientationMenu.add(new JMenuItem(dir.getName(), ARROW_ICONS[i]));
      item.setEnabled(dir != properties.getTabAreaOrientation());
      item.addActionListener((ActionEvent e) -> {
		  tabWindow.getTabWindowProperties().getTabbedPanelProperties().setTabAreaOrientation(dir);
	  });
    }

    menu.add(orientationMenu);
  }

  private static void addTabDirectionMenuItems(JPopupMenu menu, DockingWindow window) {
    final AbstractTabWindow tabWindow = getTabWindowFor(window);

    if (tabWindow == null)
      return;

    JMenu directionMenu = new JMenu(I18N.getMsg("infonode.direction"));
    TitledTabProperties properties = TitledTabProperties.getDefaultProperties();
    properties.addSuperObject(tabWindow.getTabWindowProperties().getTabProperties().getTitledTabProperties());
    final Direction[] directions = Direction.getDirections();

    for (int i = 0; i < directions.length; i++) {
      final Direction dir = directions[i];

      if (dir != Direction.LEFT) {
        JMenuItem item = directionMenu.add(new JMenuItem(dir.getName(), ARROW_ICONS[i]));
        item.setEnabled(dir != properties.getNormalProperties().getDirection());
        item.addActionListener((ActionEvent e) -> {
			tabWindow.getTabWindowProperties().getTabProperties().getTitledTabProperties().getNormalProperties()
				.setDirection(dir);
		});
      }
    }

    menu.add(directionMenu);
  }

  private static void addSplitWindowMenuItems(JPopupMenu menu, final DockingWindow window) {
    if (window instanceof SplitWindow) {
      JMenu splitMenu = new JMenu(I18N.getMsg("infonode.split"));

      splitMenu.add("25%").addActionListener((ActionEvent e) -> {
		  ((SplitWindow) window).setDividerLocation(0.25f);
	  });

      splitMenu.add("50%").addActionListener((ActionEvent e) -> {
		  ((SplitWindow) window).setDividerLocation(0.5f);
	  });

      splitMenu.add("75%").addActionListener((ActionEvent e) -> {
		  ((SplitWindow) window).setDividerLocation(0.75f);
	  });

      splitMenu.addSeparator();

      splitMenu.add(I18N.getMsg("infonode.flip")).addActionListener((ActionEvent e) -> {
		  ((SplitWindow) window).setHorizontal(!((SplitWindow) window).isHorizontal());
	  });

      splitMenu.add(I18N.getMsg("infonode.mirror")).addActionListener((ActionEvent e) -> {
		  SplitWindow sw = (SplitWindow) window;
		  sw.setWindows(window.getChildWindow(1), window.getChildWindow(0));
		  sw.setDividerLocation(1 - sw.getDividerLocation());
	  });

      menu.add(splitMenu);
    }
  }

  /**
   * Creates a factory which creates a popup menu containing common window actions.
   *
   * @param viewFactoryManager used for creating a list of views that the user can show
   * @param addTabItems        add items for changing tab direction and orientation
   * @return the window popup menu factory
   */
  public static WindowPopupMenuFactory createWindowMenuFactory(ViewFactoryManager viewFactoryManager,
                                                               boolean addTabItems) {
    return createWindowMenuFactory(viewFactoryManager, addTabItems, true);
  }

  /**
   * Creates a factory which creates a popup menu containing common window actions.
   *
   * @param viewFactoryManager  used for creating a list of views that the user can show
   * @param addTabItems         add items for changing tab direction and orientation
   * @param addSplitWindowItems add items for {@link SplitWindow}'s
   * @return the window popup menu factory
   * @since IDW 1.2.0
   */
  public static WindowPopupMenuFactory createWindowMenuFactory(final ViewFactoryManager viewFactoryManager,
                                                               final boolean addTabItems,
                                                               final boolean addSplitWindowItems) {
    return (DockingWindow window) -> {
		JPopupMenu menu = new JPopupMenu(window.getTitle());
		
		if (!(window instanceof RootWindow)) {
			if (!(window instanceof WindowBar)) {
				addWindowMenuItems(menu, window);
				menu.addSeparator();
			}
			
			if (addTabItems) {
				addTabOrientationMenuItems(menu, window);
				addTabDirectionMenuItems(menu, window);
				menu.addSeparator();
			}
			
			if (addSplitWindowItems) {
				addSplitWindowMenuItems(menu, window);
				menu.addSeparator();
			}
		}
		
		addNewViewMenuItems(menu, window, viewFactoryManager);
		MenuUtil.optimizeSeparators(menu);
		MenuUtil.align(menu);
		return menu;
	};
  }

}
