/*
 * 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 action;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

import ilog.cpl.IlpEquipment;
import ilog.cpl.datasource.IlpAbstractHierarchyAdapter;
import ilog.cpl.datasource.IlpDataSource;
import ilog.cpl.datasource.structure.IlpContainer;
import ilog.cpl.graph.IlpGraphView;
import ilog.cpl.graphic.IlpPoint;
import ilog.cpl.model.IlpObject;
import ilog.cpl.model.IlpRepresentationObject;
import ilog.tgo.faces.IltFacesPropertyAccessor;
import ilog.tgo.faces.graph.dhtml.event.IltFacesDefaultObjectAction;
import ilog.tgo.model.IltShelf;
import ilog.views.faces.IlvFacesPageIdUtil;

/**
 * This type is in charge of managing the visibility of the equipment in the
 * Equipment View. It shows or hides equipments based on the call to method
 * equipmentVisibility, which is bound to tag attribute
 * objectActionMethodBinding of the clientSelectInteractor attached to the
 * Network View.
 * 
 * This type is also in charge of managing the currently active view by binding
 * method activateEquipmentView of the clientSelectInteractor attached to the
 * EquipmentView. The client uses the JavaScript activeView variable to
 * configure the ZoomIn, ZoomOut and ShowAll interactors in the appropriate view
 * (Equipment or Network View).
 * 
 * Finally, this class also manages the currently selected object by binding
 * method selectedIds with tag attribute infoProviderMethodBinding of both the
 * clientSelectInteractors, the one attached to the Network View and the other
 * attached to the Equipment View. This information is used by the client to
 * update the JavaScript table "selectionInfo", which displays the identifier of
 * the currently selected objects in both Network and Equipment Views.
 */
public class EquipmentVisibilityHandler {
  /**
   * The default handler for object actions
   */
  private IltFacesDefaultObjectAction defaultObjectAction = new IltFacesDefaultObjectAction();

  /**
   * The PropertyAccessor used to expose the active component and the selected
   * object.
   */
  private final MyPropertyAccessor propertyAccessor = new MyPropertyAccessor();
  private final static String NetworkView = "network";
  private final static String EquipmentView = "equipment";

  /**
   * Constructor Initializes the list of selected objects with dummy info.
   */
  public EquipmentVisibilityHandler() {
    propertyAccessor.setActiveComponent(NetworkView);
  }

  /**
   * Method bound to the objectActionMethodBinding tag attribute of the
   * clientSelectInteractor attached to the Network View.
   * 
   * It identifies which object, if any, has been selected by the user,
   * displaying (or hiding) its corresponding equipment object in the Equipment
   * View.
   * 
   * A flag is added to the selectedIds (position [1]) so that the client will
   * know that the Network View has been clicked.
   */
  public boolean equipmentVisibility(IlpGraphView view, int xPos, int yPos) {
    // Get the Adapter associated with the Equipment component
    IlpAbstractHierarchyAdapter adapter = getAdapter();

    // Get the corresponding representation object, if any.
    IlpRepresentationObject repObj = view.getRepresentationObject(new IlpPoint(xPos, yPos));

    if (null == repObj) {
      // No network node selected, hide the equipment object
      adapter.setOrigins(Collections.emptyList(), true);
    } else if (!view.isLink(repObj)) {
      // Display the equipment object in the Equipment View

      // Get the corresponding business object
      IlpObject networkElement = repObj.getIlpObject();

      // Find identifier of IltShelf
      Object shelfIdentifier = getShelfIdentifier(adapter.getDataSource(), networkElement);

      // Only process if we found the shelf...
      if (shelfIdentifier != null) {
        List<Object> origins = new ArrayList<Object>(1);
        origins.add(shelfIdentifier);
        adapter.setOrigins(origins, true);
      }
    }
    // Set 'network' as the active view
    propertyAccessor.setActiveComponent(NetworkView);

    // Return the default object action, which handles
    // subnetwork expansion, information icons and etc.
    return defaultObjectAction.processObjectAction(view, xPos, yPos);
  }

  /**
   * Method bound to the objectActionMethodBinding tag attribute of the
   * clientSelectInteractor attached to the Equipment View.
   * 
   * It adds a flag to the selectedIds (position [1]) so that the client will
   * know that the Equipment View has been clicked.
   */
  public boolean activateEquipmentView(IlpGraphView view, int xPos, int yPos) {
    // Set 'equipment' as the active view
    propertyAccessor.setActiveComponent(EquipmentView);

    // Return the default object action, which handles
    // subnetwork expansion, information icons and etc.
    return defaultObjectAction.processObjectAction(view, xPos, yPos);
  }

  /**
   * Returns the IltFacesPropertyAccessor used to expose properties to the
   * client side.
   */
  public IltFacesPropertyAccessor getPropertyAccessor() {
    return propertyAccessor;
  }

  /**
   * Returns the identifier of the IltSheft that is contained by the given
   * IlpObject. If no IltSheft is contained, null is returned.
   */
  private Object getShelfIdentifier(IlpDataSource dataSource, IlpObject networkElement) {

    IlpContainer containerInterface = dataSource.getContainerInterface(networkElement);

    Collection<Object> children = containerInterface.getChildren(networkElement);

    // It should not be empty and it should only have one child
    if (!children.isEmpty()) {
      Object childIdentifier = children.iterator().next();

      IlpObject child = dataSource.getObject(childIdentifier);

      if (child instanceof IltShelf) {
        return childIdentifier;
      }
    }
    return null;
  }

  /**
   * Return the Adapter associated with the Equipment component.
   */
  private IlpAbstractHierarchyAdapter getAdapter() {
    // Retrieve the IlpEquipment component from the session
    IlpEquipment equipment = (IlpEquipment) IlvFacesPageIdUtil.getSessionAttributeWithPageId("equipment");
    // Return the adapter associated with it
    return (IlpAbstractHierarchyAdapter) equipment.getAdapter();
  }
}