/*
 * 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.configurator;

import ilog.cpl.model.IlpObject;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.StringTokenizer;

/**
 * The entity in charge of ensuring that the appropriate configuration is always 
 * loaded on the target component.
 * <p>
 * This class should be used as the base type for component configurators.
 * <p>
 * This type listens on changes in the current root and applies the approriate configuration
 * to the target component.
 */
abstract public class AbstractComponentConfigurator implements PropertyChangeListener {

  /**
   * Flag that determines if addional configuration has been loaded.
   */
  protected boolean hasLoadedAdditionalConfigs;

  public AbstractComponentConfigurator() {
    hasLoadedAdditionalConfigs = false;
  }

  /**
   * Should return the configuration file name for when the component is 
   * displaying its roots.
   *  
   * @return <code>null</code> is a valid value.
   */
  abstract protected String getRootConfiguration();

  /**
   * Should return the configuration file name that should be loaded when displying 
   * the provided object.
   * @return <code>null</code> is a valid value.
   */
  abstract protected String getDetailsConfiguration(IlpObject object);

  /**
   * Should return the stylesheet file name string (comma separate names of 
   * style file names) that are currently being applied to the target component.
   */
  abstract protected String getCurrentStyleSheets();

  /**
   * Should update the stylesheet list of the target component with the provided
   * String that contains a comma separate list of names of style files. 
   */
  abstract protected void updateStyleSheets(String styleSheets);

  /**
   * Reads the root configuration into the target component if it is not 
   * <code>null</code>. 
   */
  public void initialize() {

    //Load the default configuration if one is needed
    if (getRootConfiguration() != null) {
      readConfiguration(getRootConfiguration());
    }
  }

  /**
   * When the root property is changed this method attempts to load the 
   * appropriate configuration that pertains to it. 
   * 
   * @see java.beans.PropertyChangeListener#propertyChange(java.beans.PropertyChangeEvent)
   */
  public void propertyChange(PropertyChangeEvent evt) {

    IlpObject object = (IlpObject) evt.getNewValue();

    String configFileName = (object == null)
    ? getRootConfiguration()
        : getDetailsConfiguration(object);

    readConfiguration(configFileName);
  }

  /**
   * Reads the provided configuration file into the target component.
   * <p>
   * If other configuration file has already been loaded, it is removed first.
   */
  protected void readConfiguration(String configFile) {

    String newStyles = "";

    String currentStyles = getCurrentStyleSheets();

    if (hasLoadedAdditionalConfigs) {
      newStyles = removeLastStyle(currentStyles)
      + ((configFile != null) ? ("," + configFile) : "");
    } else {
      newStyles = currentStyles + "," + configFile;
    }

    updateStyleSheets(newStyles);

    //We have now loaded an additional config 
    hasLoadedAdditionalConfigs = true;
  }

  /**
   * Removes the last style from the provided String that should contains a 
   * comma separated list of style file names.
   */
  protected String removeLastStyle(String currentStyles) {
    int indexOfLastComma = currentStyles.lastIndexOf(",");

    if (indexOfLastComma > -1) {
      currentStyles = currentStyles.substring(0, indexOfLastComma);
    }

    return currentStyles;
  }
  
  /**
   * Returns a String[] that contains the values that are separated by commas in the 
   * provided String.
   */
  protected String[] getStringArrayForStyleString(String styles) {
    
    StringTokenizer tokenizer = new StringTokenizer(styles, ",");
    
    int numberOfTokens = tokenizer.countTokens();
    String[] array = new String[numberOfTokens];
    
    for (int i = 0; i < numberOfTokens; i++) {
      array[i] = tokenizer.nextToken();      
    }
    return array;
  }
}