/*
 * 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 monitoring.web.controls.popup;

import ilog.cpl.graph.IlpGraphView;
import ilog.cpl.model.IlpObject;
import ilog.cpl.model.IlpRepresentationObject;
import ilog.views.faces.dhtml.IlvDHTMLConstants;
import ilog.views.faces.dhtml.event.FacesViewActionListener;
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 java.util.EventObject;
import java.util.logging.Level;

import monitoring.shared.LoggingUtils;
import monitoring.web.AbstractSampleContext;

/**
 * Base class that contains common code shared accross the different contextual 
 * menu factory implementation in the sample.
 */
abstract public class AbstractContextualMenuFactory implements IlvMenuFactory {

  protected String targetFacesViewIdentifier;
  protected String contextualMenuFactoryIdentifier;
  protected AbstractSampleContext sampleContext;

  //Listeners in charge of showing the different modules
  protected FacesViewActionListener showNetworkModuleActionListener;
  protected FacesViewActionListener showServiceModuleActionListener;
  protected FacesViewActionListener showInventoryModuleActionListener;

  /**
   * Creates its internal structures.
   */
  public AbstractContextualMenuFactory() {
    showInventoryModuleActionListener = new ShowInventoryModuleActionListener();
    showNetworkModuleActionListener = new ShowNetworkModuleActionListener();
    showServiceModuleActionListener = new ShowServiceModuleActionListener();
  }

  /**
   * Saves the <code>AbstractSampleContext</code> reference.
   */
  public void initialize(AbstractSampleContext sampleContext) {
    setApplicationContext(sampleContext);
  }

  /**
   * Creates the view specific menu items.
   *
   * @param root        The root pop-up menu
   * @param activeObj   The object under the pop-up menu
   * @param menuModelId The interactor currently selected
   */
  abstract protected void createViewSpecificMenuItems(IlvMenu root,
      IlpObject businessObject, String menuModelId, IlpGraphView graphView);

  /**
   * Creates the view specific menu items.
   *
   * @param root        The root pop-up menu
   * @param activeObj   The object under the pop-up menu
   * @param menuModelId The interactor currently selected
   */
  abstract protected void createModuleNavigationMenuItems(IlvMenu root,
      String menuModelId, IlpGraphView graphView);

  /**
   * Generates the pop-up menu for the view in question.
   *
   * @param graphic      The IlpEquipmentView or IlpNetworkView 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) {

    //1- Create the root menu
    IlvMenu root = new IlvMenu("Root");

    //2- Get the underlying IlpObject
    if (activeObject instanceof IlpRepresentationObject) {

      IlpObject object = 
        ((IlpRepresentationObject) activeObject).getIlpObject();

      //3- Create the equipment menu items
      createViewSpecificMenuItems(root, object, menuModelId, (IlpGraphView) graphicComponent);
    }

    //4- Create the equipment menu items
    createModuleNavigationMenuItems(root, menuModelId, (IlpGraphView) graphicComponent);

    return root;
  }

  /**
   * Return the JavaScript action that is to be used to update the target view. 
   */
  protected String getUpdateComponentsJavaScriptAction(boolean updateMainView, boolean updateTableView, boolean updateTreeView, String newVisibleArea) {
    //Updates the table, tree and main view
    return getUpdateMethodName() + 
    "( " + updateMainView +", " + updateTableView + "," + updateTreeView +
    ((newVisibleArea==null) ? "" : ",'" + newVisibleArea + ",true,false'")
    + ")";
  }
  
  /**
   * Returns the JavaScript method name that is to be called on the client side 
   * to update the client side representation of the components.
   * <BR/>
   * This needs to be in synch with the JavaScript definitions. 
   */
  protected String getUpdateMethodName() {
    
    String updateMethodName = null;
    
    if(targetFacesViewIdentifier == "networkNetworkView") {
      updateMethodName = "forceNetworkComponentsUpdate";
    } else if(targetFacesViewIdentifier == "serviceNetworkView") {
      updateMethodName = "updateServiceComponents";
    } else if(targetFacesViewIdentifier == "inventoryEquipmentView") {
      updateMethodName = "updateInventoryComponents";
    } else {
      LoggingUtils.getSampleLogger().log(
          Level.WARNING,
          "Could not find method name to update client side representation of components.");
    }
    
    return updateMethodName;
  }

  /**
   * 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
   */
  protected void createJavaScriptMenuItem(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 server and JavaScript actions, 
   * 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
   */
  protected void createServerClientMenuItem(IlvMenu menu, String label,
      String image, String serverAction, String javaScriptAction,
      String menuItemId, boolean enabled, int invocationContext) {
    //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.
    ServerClientActionListener action = 
      new ServerClientActionListener(serverAction, javaScriptAction, invocationContext);
    IlvMenuItem item = new IlvMenuItem(label, action, image, enabled);
    item.setId(menuItemId);
    menu.addChild(item);
  }

  protected void createServerMenuItem(IlvMenu menu, String label,
      String image, FacesViewActionListener listener, boolean enabled) {
    menu.addChild(new IlvMenuItem(label, listener, image, enabled));
  }

  /**
   * Removes any trailing separator.
   */
  protected void trimContextualMenu(IlvMenu root) {

    if (root.getChildren() == null) {
      return;
    }

    int size = root.getChildren().size();

    if (size > 0) {
      IlvMenuItem item = root.getChild(size - 1);
      if (item instanceof IlvMenuSeparator) {
        root.removeChild(size - 1);
      }
    }
  }

  //////////////////////////////////////////////////////////////////////////////
  //Accessors and Modifiers
  //////////////////////////////////////////////////////////////////////////////

  public String getContextualMenuFactoryIdentifier() {
    return contextualMenuFactoryIdentifier;
  }
  public void setContextualMenuFactoryIdentifier(
      String targetFacesContextualMenuFactoryIdentifier) {
    this.contextualMenuFactoryIdentifier = targetFacesContextualMenuFactoryIdentifier;
  }
  public String getTargetFacesViewIdentifier() {
    return targetFacesViewIdentifier;
  }
  public void setTargetFacesViewIdentifier(String targetFacesViewIdentifier) {
    this.targetFacesViewIdentifier = targetFacesViewIdentifier;
  }
  public AbstractSampleContext getSampleContext() {
    return sampleContext;
  }
  public void setApplicationContext(AbstractSampleContext sampleContext) {
    this.sampleContext = sampleContext;
  }

  //////////////////////////////////////////////////////////////////////////////
  //Action Listeners
  //////////////////////////////////////////////////////////////////////////////

  public class ShowNetworkModuleActionListener extends FacesViewActionListener {

    public ShowNetworkModuleActionListener() {
      super(IlvDHTMLConstants.JSF_CONTEXT);
    }

    public void actionPerformed(EventObject event) throws Exception {
      sampleContext.getActionProviders().getSharedActions().showNetworkModule();
    }
  }

  public class ShowInventoryModuleActionListener extends FacesViewActionListener {

    public ShowInventoryModuleActionListener() {
      super(IlvDHTMLConstants.JSF_CONTEXT);
    }

    public void actionPerformed(EventObject event) throws Exception {
      sampleContext.getActionProviders().getSharedActions().showInventoryModule();
    }
  }

  public class ShowServiceModuleActionListener extends FacesViewActionListener {

    public ShowServiceModuleActionListener() {
      super(IlvDHTMLConstants.JSF_CONTEXT);
    }

    public void actionPerformed(EventObject event) throws Exception {
      sampleContext.getActionProviders().getSharedActions().showServiceModule();
    }
  }
}