/*
 * Licensed Materials - Property of Perforce Software, Inc. 
 * © Copyright Perforce Software, Inc. 2014, 2021 
 * © 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 demo;

import java.util.EventObject;

import ilog.cpl.graph.IlpGraphView;
import ilog.cpl.model.IlpAttribute;
import ilog.cpl.model.IlpRepresentationObject;
import ilog.tgo.model.IltAlarm;
import ilog.tgo.model.IltAlarmSeverity;
import ilog.tgo.model.IltObjectState;
import ilog.views.faces.dhtml.IlvDHTMLConstants;
import ilog.views.faces.dhtml.event.FacesViewActionListener;
import ilog.views.util.IlvResourceUtil;
import ilog.views.util.servlet.IlvMenuFactory;
import ilog.views.util.servlet.event.JavaScriptActionListener;
import ilog.views.util.servlet.event.ServletActionEvent;
import ilog.views.util.servlet.model.IlvMenu;
import ilog.views.util.servlet.model.IlvMenuItem;
import ilog.views.util.servlet.model.IlvMenuSeparator;

/**
 * <p>
 * This bean defines a pop-up menu factory for a network or equipment Faces
 * component by implementing the <code>IlvMenuFactory</code>, allowing the
 * creation of dynamic pop-up menus, including actions to add/remove alarms.
 */
public class MyAlarmPopupMenuFactory implements IlvMenuFactory {
  // The menu model ids
  private static final String PAN_MENU_MODEL_ID = "panItr";

  private static final String ZOOM_MENU_MODEL_ID = "zoomItr";

  private static final String SELECT_MENU_MODEL_ID = "selectItr";

  // The action listeners
  private final AddAlarmActionListener addAlarmListener = this.new AddAlarmActionListener();
  private final RemoveAlarmActionListener removeAlarmListener = this.new RemoveAlarmActionListener();

  /**
   * <p>
   * Access method to the <i>pan</i> menu model identifier.
   * 
   * @return The appropriate value for <code>menuModelId</code>
   */
  public String getPanMenuModelId() {
    return MyAlarmPopupMenuFactory.PAN_MENU_MODEL_ID;
  }

  /**
   * <p>
   * Access method to the <i>zoom</i> menu model identifier.
   * 
   * @return The appropriate value for <code>menuModelId</code>
   */
  public String getzoomMenuModelId() {
    return MyAlarmPopupMenuFactory.ZOOM_MENU_MODEL_ID;
  }

  /**
   * <p>
   * Access method to the <i>select</i> menu model identifier.
   * 
   * @return The appropriate value for <code>menuModelId</code>
   */
  public String getSelectMenuModelId() {
    return MyAlarmPopupMenuFactory.SELECT_MENU_MODEL_ID;
  }

  /**
   * <p>
   * Generates the pop-up menu.
   *
   * @param graphic
   *          The <code>IlpNetworkView</code> or <code>IlpEquipmentView</code>
   *          component
   * @param activeObject
   *          The representation object (<code>IlpRepresentationObject</code>)
   *          currently active (right below the mouse pointer)
   * @param menuModelId
   *          The menu model ID
   * @return The root menu.
   */
  Override
  public IlvMenu createMenu(Object graphicComponent, Object activeObject, String menuModelId) {
    // Create the root menu
    IlvMenu root = new IlvMenu("Root");

    // Create the menu items from interactors
    createInteractorMenuItems(root, menuModelId);

    // Create the alarm menu items
    createAlarmMenuItems(root, (IlpGraphView) graphicComponent, (IlpRepresentationObject) activeObject);
    return root;
  }

  /**
   * <p>
   * Create menu items from the interactors.
   *
   * @param root
   *          The root pop-up menu
   * @param menuModelId
   *          The interactor currently active
   */
  private void createInteractorMenuItems(IlvMenu root, String menuModelId) {
    // Create a menu item that activates (if not already active) the
    // "selectBttn" button in the JSP page
    boolean enabled = !SELECT_MENU_MODEL_ID.equals(menuModelId);
    createJSMenuItem(root, IlvResourceUtil.getCurrentLocaleString(MyAlarmPopupMenuFactory.class, "select"),
        "/resources/images/arrow.png", "selectBttn.doClick()", enabled);

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

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

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

    // Create a menu item that activates the "ftcBttn" button in the
    // JSP page
    createJSMenuItem(root, IlvResourceUtil.getCurrentLocaleString(MyAlarmPopupMenuFactory.class, "showall"),
        "/resources/images/zoomfit.png", "example17.showAll()", true);

    // Create a menu item that activates the "zoomInBttn" button in the
    // JSP page
    createJSMenuItem(root, IlvResourceUtil.getCurrentLocaleString(MyAlarmPopupMenuFactory.class, "Zoomin"),
        "/resources/images/zoom.png", "example17.zoomIn()", true);

    // Create a menu item that activates the "zoomOutBttn" button in the
    // JSP page
    createJSMenuItem(root, IlvResourceUtil.getCurrentLocaleString(MyAlarmPopupMenuFactory.class, "Zoomout"),
        "/resources/images/unzoom.png", "example17.zoomOut()", true);
  }

  /**
   * <p>
   * Create 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));
  }

  /**
   * <p>
   * Create the appropriate alarm menu items. It will allow the user to add one
   * major alarm or remove an alarm.
   * 
   * @param root
   *          The root pop-up menu
   * @param graphView
   *          The underlying <code>IlpGraphView</code>
   * @param activeObj
   *          The business object where the pop-up menu is activated
   */
  private void createAlarmMenuItems(IlvMenu root, IlpGraphView graphView, IlpRepresentationObject activeObj) {
    if (null != activeObj) {
      // Get object state from 'objectState' attribute
      IlpAttribute attrib = activeObj.getAttributeGroup().getAttribute("objectState");
      if (null == activeObj.getAttributeValue(attrib)) {
        // No menu is created if 'activeObj' has no object state.
        return;
      }

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

      // The 'add major alarm' menu item
      root.addChild(
          new IlvMenuItem(IlvResourceUtil.getCurrentLocaleString(MyAlarmPopupMenuFactory.class, "Addmajoralarm"),
              addAlarmListener, "/resources/images/addalarm.png", true));

      // The 'remove one alarm' menu item
      root.addChild(
          new IlvMenuItem(IlvResourceUtil.getCurrentLocaleString(MyAlarmPopupMenuFactory.class, "Removeonealarm"),
              removeAlarmListener, "/resources/images/clralarm.png", true));
    }
  }

  /**
   * <p>
   * Action listener that adds one major alarm to the currently active objects.
   */
  private class AddAlarmActionListener extends FacesViewActionListener {
    /**
     * <p>
     * Constructor. It uses the <code>IMAGE_SERVLET_CONTEXT</code> as no other
     * JSF component has to be updated.
     */
    public AddAlarmActionListener() {
      super(IlvDHTMLConstants.IMAGE_SERVLET_CONTEXT);
    }

    /**
     * <p>
     * Adds one major alarm to the active object.
     *
     * @param event
     *          The event object.
     */
    Override
    public void actionPerformed(EventObject event) throws Exception {
      // event is instance of ServletActionEvent
      ServletActionEvent saEvt = (ServletActionEvent) event;
      // get active object
      IlpRepresentationObject obj = (IlpRepresentationObject) saEvt.getObject();
      // get object state from 'objectState' attribute
      IlpAttribute attrib = obj.getAttributeGroup().getAttribute("objectState");
      IltObjectState oState = (IltObjectState) obj.getAttributeValue(attrib);
      if (null != oState) {
        // add 'Major' alarm to object state
        ((IltAlarm.State) oState.getAlarmState()).addNewAlarm(IltAlarm.Severity.Major);
      }
    }
  }

  /**
   * <p>
   * Action listener that removes one alarm from the currently active objects.
   */
  private class RemoveAlarmActionListener extends FacesViewActionListener {
    /**
     * <p>
     * Constructor. It uses the <code>IMAGE_SERVLET_CONTEXT</code> as no other
     * JSF component has to be updated.
     */
    public RemoveAlarmActionListener() {
      super(IlvDHTMLConstants.IMAGE_SERVLET_CONTEXT);
    }

    /**
     * <p>
     * Adds one major alarm to the active object.
     *
     * @param event
     *          The event object.
     */
    Override
    public void actionPerformed(EventObject event) throws Exception {
      // event is instance of ServletActionEvent
      ServletActionEvent saEvt = (ServletActionEvent) event;
      // get active object
      IlpRepresentationObject obj = (IlpRepresentationObject) saEvt.getObject();
      // get object state from 'objectState' attribute
      IlpAttribute attrib = obj.getAttributeGroup().getAttribute("objectState");
      IltObjectState oState = (IltObjectState) obj.getAttributeValue(attrib);
      if (null != oState) {
        IltAlarm.State alarms = (IltAlarm.State) oState.getAlarmState();
        IltAlarmSeverity severity = alarms.getHighestNewAlarmSeverity();
        if (null != severity) {
          alarms.removeNewAlarm(severity);
        }
      }
    }
  }
}