/*
 * Licensed Materials - Property of Rogue Wave Software, Inc. 
 * © Copyright Rogue Wave Software, Inc. 2014, 2015 
 * © Copyright IBM Corp. 2009, 2014
 * © Copyright ILOG 1996, 2009
 * All Rights Reserved.
 *
 * Note to U.S. Government Users Restricted Rights:
 * The Software and Documentation were developed at private expense and
 * are "Commercial Items" as that term is defined at 48 CFR 2.101,
 * consisting of "Commercial Computer Software" and
 * "Commercial Computer Software Documentation", as such terms are
 * used in 48 CFR 12.212 or 48 CFR 227.7202-1 through 227.7202-4,
 * as applicable.
 */
package popup;

import ilog.tgo.model.IltLed;

import ilog.cpl.graph.IlpGraphView;
import ilog.cpl.model.IlpRepresentationObject;

import ilog.views.util.IlvResourceUtil;
import ilog.views.util.servlet.IlvMenuFactory;
import ilog.views.util.servlet.event.JavaScriptActionListener;
import ilog.views.util.servlet.model.IlvMenu;
import ilog.views.util.servlet.model.IlvMenuItem;
import ilog.views.util.servlet.model.IlvMenuSeparator;

import action.AlarmStateActionListener;
import action.ServerClientActionListener;

/**
 * This bean defines a pop-up menu factory for the Equipment View JSF
 * component by implementing the IlvMenuFactory, allowing the creation 
 * of menu items that trigger server actions and client actions.
 */
public class PopupMenuFactory implements IlvMenuFactory {

  //////////////////////////////////////////////////////////////////////////////
  //Identifiers used in the menus for the various interactors
  //////////////////////////////////////////////////////////////////////////////
  private static final String PAN_MENU_MODEL_ID = "panInteractorId";

  private static final String ZOOM_MENU_MODEL_ID = "zoomInteractorId";

  private static final String SELECT_MENU_MODEL_ID = "selectInteractorId";

  //////////////////////////////////////////////////////////////////////////////
  //Action listener in charge of handling the alarm server actions.
  //////////////////////////////////////////////////////////////////////////////
  private AlarmStateActionListener alarmStateHandler;

  public PopupMenuFactory() {
    //Create alarm state handler
    alarmStateHandler = new AlarmStateActionListener();
  }
  
  /**
   * Returns the alarm handler used by this factory.
   */
  public AlarmStateActionListener getAlarmStateHandler() {
    return alarmStateHandler;
  }

  /**
   * Returns the <i>pan</i> menu model identifier.
   */
  public String getPanMenuModelId() {
    return PopupMenuFactory.PAN_MENU_MODEL_ID;
  }

  /**
   * Returns the <i>zoom</i> menu model identifier.
   */
  public String getzoomMenuModelId() {
    return PopupMenuFactory.ZOOM_MENU_MODEL_ID;
  }

  /**
   * Returns the <i>select</i> menu model identifier.
   */
  public String getSelectMenuModelId() {
    return PopupMenuFactory.SELECT_MENU_MODEL_ID;
  }
  
  /**
   * Generates the pop-up menu for the Equipment View.
   *
   * @param graphic      The IlpEquipmentView component
   * @param activeObject The representation object (IlpRepresentationObject)
   *                     currently active (right below the mouse pointer)
   * @param menuModelId  The menu model ID
   * 
   * @return The root menu.
   */
  public IlvMenu createMenu(Object graphicComponent, Object activeObject, 
                            String menuModelId) {
    //Create the root menu
    IlvMenu root = new IlvMenu("Root");

    //Create the equipment menu items
    createMenuItems(root, activeObject, 
                    menuModelId, (IlpGraphView)graphicComponent);      
    
    return root;
  }
  
  /**
   * Creates the menu items that are used in the Equipment pop-up menus.
   *
   * @param root        The root pop-up menu
   * @param activeObj   The object under the pop-up menu
   * @param menuModelId The interactor currently selected
   */
  private void createMenuItems(IlvMenu root, Object activeObj, 
                               String menuModelId, IlpGraphView graphView) {
    
    //1- Create the interactor menu items 
    createInteractorMenuItems(root, menuModelId);
    
    //2- Create the alarm menu items 
    createAlarmMenuItems(root, activeObj, graphView);
    
    //3- Remove any trailing separator
    trimPopupMenu(root);
  }
  
  /**
   * Creates the interactor menu items.
   *
   * @param root        The root pop-up menu
   * @param menuModelId The interactor currently selected
   */
  private void createInteractorMenuItems(IlvMenu root, String menuModelId) {

    //For following menu items take advantage of client side actions that 
    //are available on JavaScript objects that reside on the page itself.
    //They reference interctors and views that have been defined in the index.jsp 
    //file. 
    //
    //Note that when referencing resources, such as images, the full path is needed
    //as these are not goverened by the JViews TGO URLAccess Service. 
    //
    //For options of what can be done with clients action on the existing JavaScript
    //objects see the JavaScript Reference Manual in the Jviews TGO documentation.
    
    //Create a menu item that activates (if not already active) the
    //"selectButton" button in the JSP page
    boolean enabled = !SELECT_MENU_MODEL_ID.equals(menuModelId);
    createJSMenuItem(root, IlvResourceUtil.getCurrentLocaleString(PopupMenuFactory.class,"EnableSelectionMenu"), 
                           "resources/images/popup/arrow.gif",
                           "selectButton.doClick()", enabled);

    // Create a menu item that activates (if not already active) the
    // "panButton" button in the JSP page
    enabled = !PAN_MENU_MODEL_ID.equals(menuModelId);
    createJSMenuItem(root, IlvResourceUtil.getCurrentLocaleString(PopupMenuFactory.class,"EnablePanningMenu"), 
                     "resources/images/popup/pan.gif",
                     "panButton.doClick()", enabled);

    // Create a menu item that activates (if not already active) the
    // "zoomButton" button in the JSP page
    enabled = !ZOOM_MENU_MODEL_ID.equals(menuModelId);
    createJSMenuItem(root, IlvResourceUtil.getCurrentLocaleString(PopupMenuFactory.class,"EnableZoomingMenu"), 
                     "resources/images/popup/zoomrect.gif",
                     "zoomButton.doClick()", enabled);

    // Add a menu separator
    root.addChild(new IlvMenuSeparator());

    // Create a menu item that shows all the network in the client view
    createJSMenuItem(root, IlvResourceUtil.getCurrentLocaleString(PopupMenuFactory.class,"ShowallMenu"), 
                     "resources/images/popup/zoomfit.gif", 
                     "equipmentView.showAll()", true);

    // Create a menu item that zooms in the client view
    createJSMenuItem(root, IlvResourceUtil.getCurrentLocaleString(PopupMenuFactory.class,"ZoominMenu"), 
                     "resources/images/popup/zoom.gif",
                     "equipmentView.zoomIn()", true);

    // Create a menu item that zooms out the client view
    createJSMenuItem(root, IlvResourceUtil.getCurrentLocaleString(PopupMenuFactory.class,"ZoomoutMenu"), 
                     "resources/images/popup/unzoom.gif",
                     "equipmentView.zoomOut()", true);
    
    // Add a menu separator
    root.addChild(new IlvMenuSeparator());
  }   
  
  /**
   * Creates the appropriate alarm menu items
   * 
   * @param root       The root pop-up menu
   * @param activeObj  The object under the pop-up menu
   * @param graphView  The underlying IlpGraphView
   */
  private void createAlarmMenuItems(IlvMenu root, Object activeObj, 
                                    IlpGraphView graphView) {
    
    //The following menu items trigger server side actions. So when the menu item
    //is selected the ActionListener provided, in this case an instance of 
    //AlarmStateActionListener, its actionPerformed method will be called so that the 
    //appropriate action can be carried.
    
    //Only if we have a selected object
    if (isValidActiveObject(activeObj)) {
      
      //////////////////////////////////////////////////////////////////////////
      //ADD
      //////////////////////////////////////////////////////////////////////////
      
      //MAJOR
      this.createMiscMenuItem(root, IlvResourceUtil.getCurrentLocaleString(PopupMenuFactory.class,"AddMajorAlarmMenu"), null,
                              "#{popupMenuFactory.alarmStateHandler.menuAction}",
                              "enableUpdate = false; networkView.updateImage(true)",
                              AlarmStateActionListener.ADD_MAJOR_ID,
                              true);
      
      //MINOR
      this.createMiscMenuItem(root, IlvResourceUtil.getCurrentLocaleString(PopupMenuFactory.class,"AddMinorAlarmMenu"), null,
                              "#{popupMenuFactory.alarmStateHandler.menuAction}",
                              "enableUpdate = false; networkView.updateImage(true)",
                              AlarmStateActionListener.ADD_MINOR_ID,
                              true);
      
      //WARNING
      this.createMiscMenuItem(root, IlvResourceUtil.getCurrentLocaleString(PopupMenuFactory.class,"AddWarningAlarmMenu"), null,
                              "#{popupMenuFactory.alarmStateHandler.menuAction}",
                              "enableUpdate = false; networkView.updateImage(true)",
                              AlarmStateActionListener.ADD_WARNING_ID,
                              true);
            
      //Add a menu separator
      root.addChild(new IlvMenuSeparator());      
      
      //////////////////////////////////////////////////////////////////////////
      //REMOVE
      //////////////////////////////////////////////////////////////////////////
      
      //MAJOR
      this.createMiscMenuItem(root, IlvResourceUtil.getCurrentLocaleString(PopupMenuFactory.class,"RemoveMajorAlarmMenu"), null,
                              "#{popupMenuFactory.alarmStateHandler.menuAction}",
                              "enableUpdate = false; networkView.updateImage(true)",
                              AlarmStateActionListener.REMOVE_MAJOR_ID,
                              true);
      
      //MINOR
      this.createMiscMenuItem(root, IlvResourceUtil.getCurrentLocaleString(PopupMenuFactory.class,"RemoveMinorAlarmMenu"), null,
                              "#{popupMenuFactory.alarmStateHandler.menuAction}",
                              "enableUpdate = false; networkView.updateImage(true)",
                              AlarmStateActionListener.REMOVE_MINOR_ID,
                              true);
      
      //WARNING
      this.createMiscMenuItem(root, IlvResourceUtil.getCurrentLocaleString(PopupMenuFactory.class,"RemoveWarningAlarmMenu"), null,
                              "#{popupMenuFactory.alarmStateHandler.menuAction}",
                              "enableUpdate = false; networkView.updateImage(true)",
                              AlarmStateActionListener.REMOVE_WARNING_ID,
                              true);
      
      //Add a menu separator
      root.addChild(new IlvMenuSeparator());      

      //ALL
      this.createMiscMenuItem(root, IlvResourceUtil.getCurrentLocaleString(PopupMenuFactory.class,"RemoveAllAlarmsMenu"), null,
                              "#{popupMenuFactory.alarmStateHandler.menuAction}",
                              "enableUpdate = false; networkView.updateImage(true)",
                              AlarmStateActionListener.REMOVE_ALL_ID,
                              true);
      
      // Add a menu separator
      root.addChild(new IlvMenuSeparator());
    }
  }
    
  /**
   * Creates a menu item that triggers a JavaScript action, adding
   * it into a given menu.
   *
   * @param menu     The menu where the item should be added to 
   * @param label    The label of the menu item
   * @param image    The icon of the menu item
   * @param jsAction The JavaScript action to be triggered
   * @param enabled  Whether the menu item is enabled or not
   */
  private void createJSMenuItem(IlvMenu menu, String label, String image, 
                                String jsAction, boolean enabled) {
    JavaScriptActionListener action = new JavaScriptActionListener();
    action.setJsAction(jsAction);
    menu.addChild(new IlvMenuItem(label, action, image, enabled));    
  }
  
  /**
   * Creates a menu item that triggers both JavaScript and
   * server action, adding it into a given menu.
   * 
   * @param menu       The menu where the item should be added to
   * @param label      The lagel of the menu item
   * @param image      The icon of the menu item
   * @param srvAction  The server action to be triggered
   * @param jsAction   The JavaScript action to be triggered
   * @param menuItemId The action identifier
   * @param enabled    Whether the menu item is enabled or not
   */
  private void createMiscMenuItem(IlvMenu menu, String label, String image, 
                                  String srvAction, String jsAction, 
                                  String menuItemId, boolean enabled) {
    //The ServerClientActionListener gets two parameters, the first one is
    //the expression language code segment to a method binding that will be
    //invoked when the action is triggered. The second parameter is the 
    //JavaScript code that will be executed in the client right when the
    //action is triggered.
    JavaScriptActionListener action = new ServerClientActionListener(srvAction, jsAction, true);
    IlvMenuItem item = new IlvMenuItem(label, action, image, enabled);
    item.setId(menuItemId);
    menu.addChild(item);    
  }
  
  /**
   * Removes any trailing separator.
   */
  private void trimPopupMenu(IlvMenu root) {
    
    int size = root.getChildren().size();
    
    if(size > 0 ){
      IlvMenuItem item =  root.getChild(size-1);
      if (item instanceof IlvMenuSeparator) {
        root.removeChild(size-1);
      }
    }
  }

  /**
   * Identifies whether the alarm menu items should be created
   * or not. 
   */
  private boolean isValidActiveObject(Object activeObject) {
    if (activeObject instanceof IlpRepresentationObject) {
      return !(((IlpRepresentationObject)activeObject).getAttributeValue("type") instanceof IltLed.Type);
    }
    return false;
  }
}