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

import ilog.tgo.faces.IltFacesPropertyAccessor;
import ilog.tgo.faces.graph.dhtml.event.IltFacesDefaultObjectAction;
import ilog.tgo.model.IltShelf;

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.views.faces.IlvFacesPageIdUtil;

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


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