/*
 * 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.model.integration.beans;

import ilog.cpl.model.IlpObject;
import ilog.tgo.model.IltAlarm;
import ilog.tgo.model.IltCardCarrier;
import ilog.tgo.model.IltNetworkElement;
import ilog.tgo.model.IltObject;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

import monitoring.web.utils.AlarmStylingUtils;
import monitoring.web.utils.ObjectStylingUtils;
import monitoring.web.utils.ServiceStylingUtils;
import monitoring.web.utils.WebUtils;
import shared.ResourceUtils;

/**
 * Wrapper object that is used to expose the TGO data model objects as live beans.
 * <p>
 * Instances of this type are used in the integrated data models. 
 * <p>
 * <b>Important:</b> This type provides two additional peices of functionality that 
 * are not charateristic of wrapper implementations:
 * <ol>
 * <li>It provides the entry point for user interactions to trigger server side 
 * actions in the <code>selectObject</code> method.
 * <li>It provides additional processing of raw TGO model properties to expose these 
 * in a more user friendly manner by performing additional processing of these raw 
 * values. This additional processing is either delegated to an utility class or 
 * done locally. 
 * </ol>
 */
public class TGOObject implements Comparable<TGOObject> {

  /**
   * TGO model object being wrapped.
   */
  private IlpObject tgoObject;

  /**
   * Mapping of static TGO model property values to user friendly values.
   */
  private Map<String,String> probableCausesMap;

  /**
   * Default constructor.
   */
  public TGOObject() {
  }

  /**
   * Returns the target TGO model object.
   */
  public IlpObject getTgoObject() {
    return tgoObject;
  }

  /**
   * Sets the target TGO model object.
   */
  public void setTgoObject(IlpObject tgoObject) {
    this.tgoObject = tgoObject;
  }

  //////////////////////////////////////////////////////////////////////////////
  //Common Properties
  //////////////////////////////////////////////////////////////////////////////

  /**
   * Used by all network, inventory and service objects.
   */
  public String getIdentifier() {
    return tgoObject.getIdentifier().toString();
  }

  /**
   * Used by all network, inventory and service objects.
   */
  public String getName() {
    return processValueNotSet(IltObject.NameAttribute.getName());
  }

  /**
   * Used by all network and inventory objects.
   */
  public String getNewAlarmCount() {
    return processValueNotSet(IltObject.NewAlarmCountAttribute.getName());
  }

  /**
   * Used by all network and inventory objects.
   */
  public String getAlarmCount() {
    return processValueNotSet(IltObject.AlarmCountAttribute.getName());
  }

  /**
   * Used by all network and inventory objects.
   */
  public String getPrimaryState() {
    return processValueNotSet(IltObject.PrimaryStateAttribute.getName());
  }

  /**
   * Used by all network and inventory objects.
   */
  public String getSecondaryStates() {
    return processValueNotSet(IltObject.SecondaryStatesAttribute.getName());
  }

  /**
   * Used by Network Elements, OffPageConnectors, LEDs and Ports.
   */
  public String getType() {
    return processValueNotSet(IltNetworkElement.TypeAttribute.getName());
  }

  //////////////////////////////////////////////////////////////////////////////
  //Inventory Objects Properties
  //////////////////////////////////////////////////////////////////////////////

  /**
   * Used by CardCarriers.
   */
  public String getSlotCount() {
    return processValueNotSet(IltCardCarrier.SlotCountAttribute.getName());
  }

  //////////////////////////////////////////////////////////////////////////////
  //Alarms Objects Properties
  //////////////////////////////////////////////////////////////////////////////

  /**
   * Used by all alarms.
   */
  public String getAlarmNotificationIdentifier() {
    return processValueNotSet(IltAlarm.NotificationIdAttribute.getName());
  }

  /**
   * Used by all alarms.
   */
  public String getAlarmPerceivedSeverity() {
    return processValueNotSet(IltAlarm.PerceivedSeverityAttribute.getName());
  }

  /**
   * Used by all alarms.
   */
  public String getAlarmAcknowledgedState() {
    return processValueNotSet(IltAlarm.AlarmAckStateAttribute.getName());
  }

  /**
   * Used by all alarms.
   */
  public String getAlarmRaisedTime() {
    return processValueNotSet(IltAlarm.AlarmRaisedTimeAttribute.getName());
  }

  /**
   * Used by all alarms.
   */
  public String getAlarmManagedObjectIdentifier() {
    return processValueNotSet(IltAlarm.ManagedObjectInstanceAttribute.getName());
  }

  /**
   * Used by all alarms.
   */
  public String getAlarmProbableCause() {

    //Additional processing to make TGO property model values more user friendly. 
    if(probableCausesMap == null) {
      probableCausesMap = new HashMap<String,String>();

      Object[] probableCauses 
      = WebUtils.getFieldsOfType(IltAlarm.ProbableCause.class, IltAlarm.ProbableCause.class);

      Locale locale = WebUtils.getSampleContext().getTgoContext().getLocale();
      for (int i = 0; i < probableCauses.length; i++) {
        IltAlarm.ProbableCause probableCause = (IltAlarm.ProbableCause)probableCauses[i];
        probableCausesMap.put(probableCause.getName(), probableCause.getLabel(locale));      
      }
    }
    Object attributeValue = processValueNotSet(IltAlarm.ProbableCauseAttribute.getName());

    Object attributeLabel = probableCausesMap.get(attributeValue);

    if (attributeLabel == null) {
      attributeLabel = ResourceUtils.getString("labelUnknownProbableCause");
    }
    return attributeLabel.toString();
  }

  //////////////////////////////////////////////////////////////////////////////
  //Service Objects Properties
  //////////////////////////////////////////////////////////////////////////////

  /**
   * Used by "Customer".
   */
  public String getCustomerType() {
    return processValueNotSet("CustomerType");
  }

  /**
   * Used by SLA and Service.
   */
  public String getCustomer() {
    return processValueNotSet("Customer");
  }

  /**
   * Used by Service.
   */
  public String getSlaInstance() {
    return processValueNotSet("SLAInstance");
  }

  /**
   * Used by Service.
   */
  public String getSlaProfile() {
    return processValueNotSet("SLAProfile");
  }
  /**
   * Used by Service.
   */
  public String getMtbf() {
    return processValueNotSet("MTBF");
  }
  /**
   * Used by Service.
   */
  public String getAvailability() {
    return processValueNotSet("Availability");
  }
  /**
   * Used by Service.
   */
  public String getServiceType() {
    return processValueNotSet("ServiceElementType");
  }
  /**
   * Used by Service.
   */
  public String getThroughput() {
    return processValueNotSet("Throughput");
  }
  /**
   * Used by Service.
   */
  public String getProfileColor() {
    return ServiceStylingUtils.getProfileColor(tgoObject);
  }
  /**
   * Used by Service.
   */
  public String getProfileName() {
    return ServiceStylingUtils.getProfileName(tgoObject);
  }


  //////////////////////////////////////////////////////////////////////////////
  //Styling properties
  //////////////////////////////////////////////////////////////////////////////
  /**
   * Service tiny image<p>
   * In an Trinidad table/tree, it should be used as:
   * < tr:image source="#{node.serviceTinyIcon}"/ >
   */
  public String getServiceTinyIcon() {
    return ServiceStylingUtils.getIconURI(tgoObject);
  }
  /**
   * Managed object tiny image<p>
   * In an Trinidad table/tree, it should be used as:
   * < tr:image source="#{node.objectTinyIcon}"/ >
   */
  public String getObjectTinyIcon() {
    return ObjectStylingUtils.getIconURI(tgoObject);
  }
  /**
   * Alarm icon<p>
   * In an Trinidad table/tree, it should be used as:
   * < tr:image source="#{node.alarmImage}"/ >
   */
  public String getAlarmIcon() {
    return AlarmStylingUtils.getIconURI(tgoObject);
  }
  /**
   * Alarm color<p>
   * In as Trinidad table, it should be used as:
   * < tr:commandButton text="#{node.alarmName}" inlineStyle="#{node.alarmColor}"/ >
   */
  public String getAlarmColor() {
    return AlarmStylingUtils.getAlarmColor(tgoObject);
  }
  /**
   * Alarm name<p>
   * In as Trinidad table, it should be used as:
   * < tr:commandButton text="#{node.alarmName}" inlineStyle="#{node.alarmColor}"/ >
   */
  public String getAlarmName() {
    return AlarmStylingUtils.getAlarmName(tgoObject);
  }
  /**
   * Alarm acknowledge icon<p>
   * In as Trinidad table, it should be used as:
   * < tr:image source="#{node.acknowledgeAlarmIcon}""/ >
   */
  public String getAcknowledgeAlarmIcon() {
    return AlarmStylingUtils.getAckIconURI(tgoObject);
  }

  public String getObjectStyle() {
    return "font-family: Arial; font-size: 12px; color: #333333; font-weight: normal;";
  }

  
  /**
   * Entry point triggering the selection of a given object in the UI.
   * <p>
   * Delegates the actual process of selecting to an action provider.
   */
  public void selectObject() {
    WebUtils.getSampleContext().getActionProviders()
    .getSharedActions().setSelectedObject(getTgoObject());
  }
  
  /**
   * Implements the comparison based on the "name" property.
   * 
   * @see java.lang.Comparable#compareTo(T)
   */
  public int compareTo(TGOObject object) {
    String thisName = getName();
    String otherName = ((TGOObject) object).getName();

    if (thisName != null) {
      return thisName.compareTo(otherName);
    } else if (otherName == null) {
      return -1;
    } else {
      return 1;
    }
  }

  /**
   * Returns the value of the provided property in the TGO model object.
   * It performs additional processing if the property is date by properly formating 
   * it. Or if the property is not set it uses the default value of an empty string. 
   */
  private String processValueNotSet(String attribute) {

    Object attributeValue = tgoObject.getAttributeValue(attribute);

    if ((attributeValue == null) || 
        (IltObject.VALUE_NOT_SET.equals(attributeValue))) {
      attributeValue = "";
    } else if (attributeValue instanceof Date) {
      SimpleDateFormat df = 
        new SimpleDateFormat(ResourceUtils.getString("dateStringFormatAlarmRaised"));
      attributeValue = df.format((Date) attributeValue);
    } else {
      attributeValue = attributeValue.toString();
    }

    return (String) attributeValue;
  }
}