/*
 * 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.
 */
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.logging.Logger;

import ilog.cpl.IlpEquipment;
import ilog.cpl.IlpNetwork;
import ilog.cpl.datasource.IlpDefaultDataSource;
import ilog.cpl.model.IlpClass;
import ilog.cpl.service.IlpContext;
import ilog.cpl.service.IlpDefaultContext;
import ilog.tgo.IltSystem;
import ilog.tgo.faces.equipment.component.IltFacesEquipmentView;
import ilog.tgo.faces.network.component.IltFacesNetworkView;
import ilog.tgo.faces.service.IltFacesDefaultContext;
import ilog.tgo.model.IltLink;
import ilog.tgo.model.IltNetworkElement;
import ilog.tgo.resource.IltSettings;
import ilog.views.faces.IlvFacesPageIdUtil;

/**
 * <p>
 * This is the context object that provides the objects needed for this sample
 * to function properly. It is the place where the initialization of such
 * objects should be handled.
 * </p>
 * 
 * <p>
 * In order to provide multiple browser pages, some objects must be uniquely
 * associated with one browser page alone (page-specific context). These objects
 * are:
 * </p>
 * <ul>
 * <li><code>IlpDataSource</code></li>
 * <li><code>IlpNetwork</code></li>
 * <li><code>IlpEquipment</code></li>
 * </ul>
 * <p>
 * All other objects can be shared between multiple browser pages.
 * </p>
 */
public class SampleContext {

  /**
   * The default deployment file.
   */
  private static String DEPLOYMENT_FILE = "resources/configuration/deployment/deploy.xml";

  /**
   * Styles for the equipment component.
   */
  private static String EQUIPMENT_STYLES = "equipment.css";

  /**
   * Styles for the network component.
   */
  private static String NETWORK_STYLES = "network.css";

  /**
   * The network data.
   */
  private static String NETWORK_DATA_FILE = "network.xml";

  /**
   * The sample's TGO context.
   */
  private IlpContext context;

  /**
   * Support for logging error messages.
   */
  public Logger logger;

  /**
   * Constructor. Creates the TGO context and initializes it.
   */
  public SampleContext() {
    // Make sure this method is thread safe. TGO initialization in Web
    // Applications must happen in thread-safe environments to prevent two
    // distinct clients trying to initialize the static resources at the
    // same time
    synchronized (IltFacesDefaultContext.class) {
      // Initialize logger for this sample
      logger = createLogger("integration.equipment.viewer");

      // Initialize the TGO runtime
      try {
        IltSystem.Init();
      } catch (Exception e) {
        logger.severe("Could not initialize TGO with this exception: " + e.getLocalizedMessage());
      }

      // Create the context
      context = createContext();

      // Initialize the context
      if (context instanceof IlpDefaultContext) {
        ((IlpDefaultContext) context).setDeploymentFile(DEPLOYMENT_FILE);
      }

      // Initialize sample
      initializeSample();
    }
  }

  //////////////////////////////////////////////////////////////////////////////
  // Logger
  //////////////////////////////////////////////////////////////////////////////
  /**
   * Creates a logger to be used in this sample
   * 
   * @param name
   *          Logger name
   * @return Logger instance
   * @see java.util.logging.Logger
   */
  protected static Logger createLogger(String name) {
    return Logger.getLogger(name);
  }

  //////////////////////////////////////////////////////////////////////////////
  // Objects Accessors
  //////////////////////////////////////////////////////////////////////////////
  /**
   * Sets the IlpContext being used by the sample.
   */
  public IlpContext getContext() {
    return context;
  }

  /**
   * Returns the IlpDefaultDataSource that is used by the sample.
   */
  private IlpDefaultDataSource getDataSource() {
    // Tries to retrieve the Data Source from the
    // session, based on the page identifier
    IlpDefaultDataSource datasource = (IlpDefaultDataSource) IlvFacesPageIdUtil
        .getSessionAttributeWithPageId("datasource");
    if (null == datasource) {
      // Data Source has not been created yet. Create it now.
      datasource = createDataSource();
      IlvFacesPageIdUtil.setSessionAttributeWithPageId("datasource", datasource);
    }
    return datasource;
  }

  /**
   * Returns the IlpNetwork that is used by the sample.
   */
  public IlpNetwork getNetwork() {
    // Tries to retrieve the Network component from the
    // session, based on the page identifier
    IlpNetwork network = (IlpNetwork) IlvFacesPageIdUtil.getSessionAttributeWithPageId("network");
    if (null == network) {
      // Network component has not been created yet. Create it now.
      network = createNetwork();
      IlvFacesPageIdUtil.setSessionAttributeWithPageId("network", network);
    }
    return network;
  }

  /**
   * Returns the IlpEquipment that is used by the sample.
   */
  public IlpEquipment getEquipment() {
    // Tries to retrieve the Equipment component from the
    // session, based on the page identifier
    IlpEquipment equipment = (IlpEquipment) IlvFacesPageIdUtil.getSessionAttributeWithPageId("equipment");
    if (null == equipment) {
      // Equipment component has not been created yet. Create it now.
      equipment = createEquipment();
      IlvFacesPageIdUtil.setSessionAttributeWithPageId("equipment", equipment);
    }
    return equipment;
  }

  //////////////////////////////////////////////////////////////////////////////
  // Context
  //////////////////////////////////////////////////////////////////////////////
  /**
   * Should create the IlpContext that will be used by the sample. The default
   * implementation creates an instance of IltFacesDefaultContext.
   */
  protected IlpContext createContext() {
    return new IltFacesDefaultContext();
  }

  //////////////////////////////////////////////////////////////////////////////
  // DataSource
  //////////////////////////////////////////////////////////////////////////////
  /**
   * Creates the IlpDefaultDataSource that will be used by the sample.
   */
  protected IlpDefaultDataSource createDataSource() {
    IlpDefaultDataSource dataSource = new IlpDefaultDataSource(getContext());
    dataSource.setFileName(NETWORK_DATA_FILE);
    return dataSource;
  }

  //////////////////////////////////////////////////////////////////////////////
  // Components
  //////////////////////////////////////////////////////////////////////////////
  /**
   * Creates the IlpNetwork that will be used by the sample. Note that the
   * default Faces configuration file is used.
   */
  protected IlpNetwork createNetwork() {

    // Get the default configuration file name
    String config = IltFacesNetworkView.DefaultConfigurationFileName;
    IlpNetwork network = new IlpNetwork(config, getContext());

    try {

      // Adjust the what types of objects can be viewed in the main view.
      // We only want to show IltNetworkElement and IltLink in the main view
      List<IlpClass> classes = new ArrayList<IlpClass>(2);
      classes.add(IltNetworkElement.GetIlpClass());
      classes.add(IltLink.GetIlpClass());
      network.getAdapter().setAcceptedClasses(classes);

      // Set styles...
      String[] styles = { NETWORK_STYLES };
      network.setStyleSheets(styles);

      // Share the in-memory datasource instance...
      network.setDataSource(getDataSource());

    } catch (Exception e) {
      logger.severe("Cannot set the setup the network component with this exception:\n" + e.getLocalizedMessage());
    }

    return network;
  }

  /**
   * Creates the IlpEquipment that will be used by the sample. Note that the
   * default Faces configuration file is used.
   */
  protected IlpEquipment createEquipment() {

    // Get the default configuration file name
    String config = IltFacesEquipmentView.DefaultConfigurationFileName;
    IlpEquipment equipment = new IlpEquipment(config, getContext());

    try {
      // Configure the adapter to show no objects by default
      List<Object> empty = Collections.emptyList();
      equipment.getAdapter().setOrigins(empty, true);

      // Set styles...
      String[] styles = { EQUIPMENT_STYLES };
      equipment.setStyleSheets(styles);

      // Share the in-memory datasource instance...
      equipment.setDataSource(getDataSource());

    } catch (Exception e) {
      logger.severe("Cannot set the setup the equipment component with this exception:\n" + e.getLocalizedMessage());
    }
    return equipment;
  }

  /**
   * Performs the sample initializations.
   */
  private void initializeSample() {

    // Initialize samples' custom types
    try {
      IltSettings settings = new IltSettings(getContext());
      String[] settingsArray = { "settings.css" };
      settings.setStyleSheets(settingsArray);
    } catch (Exception e) {
      logger.severe("Exception caught while loading sample settings:\n" + e.getLocalizedMessage());
    }
  }
}