/*
 * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
 * This software is the proprietary information of Sun Microsystems, Inc.
 * Use is subject to license terms.
 *
 * Copyright 2004 Sun Microsystems, Inc.  Tous droits réservés.
 * Ce logiciel est propriété de Sun Microsystems, Inc.
 * Distribué par des licences qui en restreignent l'utilisation.
 *
 * ident        "@(#)CIBAvailabilityStatusStateImpl.java 1.16     04/07/15 SMI"
 *
 */

package com.sun.mfwk.cib.sdk.states;

// jdk
import java.util.Map;
import java.util.logging.Logger;

// cib
import com.sun.mfwk.cib.states.CIBAvailabilityStatusState;
import com.sun.mfwk.cib.states.CIBOperationalStatusState;
import com.sun.mfwk.cib.CIBException;

import com.sun.mfwk.cib.CIBException;
import com.sun.mfwk.cib.CIBIOException;
import com.sun.mfwk.cib.CIBAttributeNotFoundException;

// Java ES-MF sdk
import com.sun.mfwk.util.log.MfLogService;
import com.sun.mfwk.util.instrum.MfStatusMBean;
import com.sun.mfwk.cib.sdk.conn.CIBConnection;

// jmx
import javax.management.MBeanServerConnection;
import javax.management.MalformedObjectNameException;

/**
 * Provides a default implementation for a CIBAvailabilityStatusState object.
 * This implementation is fully based on the Java-ES MF Instrumentation SDK.
 */
public class CIBAvailabilityStatusStateImpl
    implements CIBAvailabilityStatusState {

  private static final Logger logger = MfLogService.getLogger("cib-sdk");
  private static final String className = "CIBAvailabilityStatusStateImpl";

  protected static String STR_NORMAL = "NORMAL";
  protected static String STR_DEGRADED = "DEGRADED";
  protected static String STR_CONGESTED = "CONGESTED";
  protected static String STR_SEPARATOR = "\n";

  private CIBConnection myConnection;

  private boolean isInitialized = false;
  private boolean isStarted = false;

  /**
   * Constructor
   * @param connection MBeanServerConnection
   * @param map Map
   */
  public CIBAvailabilityStatusStateImpl(
      MBeanServerConnection connection,
      Map map) {
    logger.entering(className, "Constructor");
    myConnection = new CIBConnection(connection, map);
    logger.exiting(className, "constructor");
  }

  /**
   * Returns a last change time of the Availabilit status
   * If the attribute could not be retrieved then the last change is
   * the current system time
   * If the provider is not initialized then the last change time is -1
   * @return long
   */
  public long getLastChange() {
    logger.entering(className, "getLastChange");
    if (isStarted == true) {
      try {
        logger.finest(className + " State Provider started");
        logger.finest(className + " getAttribute AvailStateLastChange");
        Long value = new Long(myConnection.getAttribute("AvailStateLastChange").
                              getValue().
                              toString());
        logger.exiting(className, "getLastChange", value);
        return value.longValue();
      }
      catch (Exception e) {
        logger.throwing(className, "getLastChange", e);
        return System.currentTimeMillis();
      }
    }
    else {
      logger.finest(className + " State Provider not started");
      logger.exiting(className, "getLastChange", new Long( -1));
      return -1;
    }
  }

  /**
   * Returns the current availability status of the object
   * If the availability status could not be retrieve then the state is CIBOperationalStatusState.FAILED
   * If the provider is not initialized or a communication failure occurs then the availability status is FAILED;
   * @return int
   */
  public int getState() {
    logger.entering(className, "getState");
    int status;
    if (isStarted == true) {

      try {
        logger.finest(className + " State Provider started");
        logger.finest(className + " getAttribute AvailabilityState");
        Integer value = new Integer(myConnection.getAttribute(
            "AvailabilityState").
                                    getValue().toString());
        logger.exiting(className, "getState", value);
        status = value.intValue();
        return status;
      }
      catch (Exception e) {
        logger.throwing(className, "getState", e);
        return CIBOperationalStatusState.FAILED;
      }
    }
    else {
      logger.finest(className + " State Provider not started");
      logger.exiting(className, "getState", new Long( -1));
      return CIBOperationalStatusState.FAILED;
    }
  }

  /**
   * Returns the availability status into a human readable String
   * @return String
   */
  public String toStateString() {
    logger.entering(className, "toStateString");
    if (isStarted == true) {
      logger.finest(className + " State Provider started");
      logger.finest(className + " getAttribute AvailabilityState");
      int value = getState();
      String result = new String();
      switch (value) {
        case 5:
          result = STR_NORMAL;
          break;
        case 6:
          result = STR_DEGRADED;
          break;
        case 7:
          result = STR_CONGESTED;
          break;
        default:
          result = "FAILED";
      }
      logger.exiting(className, "toStateString", result);
      return result;
    }
    else {
      logger.finest(className + " State Provider not started");
      logger.exiting(className, "toStateString", null);
      return null;
    }
  }

  /**
   * Returns the time on which the Availability status entered into a Degraded state
   * @return long
   */
  public long getDegradedTime() {
    logger.entering(className, "getDegradedTime");
    if (isStarted == true) {
      try {
        logger.finest(className + " State Provider started");
        logger.finest(className + " getAttribute DegradedTime");
        Long value = new Long(myConnection.getAttribute("DegradedTime").
                              getValue().
                              toString());
        logger.exiting(className, "getDegradedTime", value);
        return value.longValue();
      }
      catch (Exception e) {
        logger.throwing(className, "getDegradedTime", e);
        logger.exiting(className, "getDegradedTime", new Long( -1));
        return -1;
      }
    }
    else {
      logger.finest(className + " State Provider not started");
      logger.exiting(className, "getDegradedTime", new Long( -1));
      return -1;
    }
  }

  /**
   * Initialize the communication mechanism. In particular, initialize the
   * communication to the instrumentation layer.
   */
  public void init() throws CIBIOException, CIBException {
    logger.entering(className, "init");
    if (isInitialized == false) {
      logger.finest(className + " State Provider is not initialized");
      this.stop();
      this.start();
      isInitialized = true;
      isStarted = true;
      logger.finest(className + " State Provider is initialized");
    }
    else {
      logger.finest(className + " State Provider already initialized");
    }
    logger.exiting(className, "init");
  }

  /**
   * destroy the states and clean the states objects/values
   * when needed, close all the communications.
   */
  public void destroy() throws CIBIOException, CIBIOException {
    logger.entering(className, "destroy");
    if (isInitialized == true) {
      logger.finest(className + " State Provider is initialized");
      isInitialized = false;
      logger.finest(className + " State Provider is destroy");
    }
    else {
      logger.finest(className + " State Provider already destroy");
    }
    logger.exiting(className, "destroy");
  }

  /**
   * Start the statistics collections and clean the statistics objects/values
   * when needed, close all the communications.
   */
  protected void start() {
    logger.entering(className, "start");
    if (isStarted == false) {
      logger.finest(className + " State Provider is not started");
      isStarted = true;
      logger.finest(className + " State Provider is started");
    }
    else {
      logger.finest(className + " State Provider already started");
    }
    logger.exiting(className, "start");
  }

  /**
   * Stop the states collections and clean the states objects/values
   * when needed, close all the communications.
   */
  protected void stop() {
    logger.entering(className, "stop");
    if (isStarted == true) {
      logger.finest(className + " State Provider is started");
      isStarted = false;
      logger.finest(className + " State Provider is stopped");
    }
    else {
      logger.finest(className + " State Provider already stopped");
    }
    logger.exiting(className, "stop");
  }

  /**
   * Returns the global status object attributes into a human readable String
   * @return String
   */
  public String toString() {
    String result = new String("AvailabilityStatus:");
    result = result + "State=" + this.getState() + STR_SEPARATOR;
    result = result + "StateString=" + this.toStateString() + STR_SEPARATOR;
    result = result + "LastChange=" + this.getLastChange() + STR_SEPARATOR;
    result = result + "DegradedTime=" + this.getDegradedTime() +
        STR_SEPARATOR;
    return result;
  }
}
