/*
 * 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        "@(#)CIBOperationalStatusStateImpl.java 1.17     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.CIBOperationalStatusState;
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.cib.sdk.conn.CIBConnection;
import com.sun.mfwk.util.log.MfLogService;

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

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

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

  private int lastKnownStatus = CIBOperationalStatusState.FAILED;
  private long lastKnownChange = System.currentTimeMillis();

  protected static String STR_STARTING = "STARTING";
  protected static String STR_STOPPING = "STOPPING";
  protected static String STR_RUNNING = "RUNNING";
  protected static String STR_STOPPED = "STOPPED";
  protected static String STR_FAILED = "FAILED";

  protected static String STR_SEPARATOR = "\n";

  private CIBConnection myConnection = null;
  private boolean isInitialized = false;
  private boolean isStarted = false;

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

  /**
   * Get the LastChange time of the operationla status object
   * @return long
   */
  public long getLastChange() {
    logger.entering(className, "getLastChange");
    if (isStarted == true) {
      try {
        logger.finest(className + " State Provider started");
        logger.finest(className + " getAttribute OpsStateLastChange");
        Long value = new Long(myConnection.getAttribute("OpsStateLastChange").
                              getValue().
                              toString());

        logger.exiting(className, "getLastChange", value);
        lastKnownChange = value.longValue();
        return lastKnownChange;
      }
      catch (Exception e) {
        logger.throwing(className, "getLastChange", e);
        return lastKnownChange;
      }
    }
    else {
      logger.finest(className + " State Provider not started");
      logger.exiting(className, "getLastChange", new Long( -1));
      return -1;
    }
  }

  /**
   * getState
   *
   * @return int
   */
  public int getState() {
    logger.entering(className, "getState");
    if (isStarted == true) {
      try {
        logger.finest(className + " State Provider started");
        logger.finest(className + " getAttribute OperationalState");
        Attribute attribute = myConnection.getAttribute("OperationalState");
        Integer value = new Integer(attribute.getValue().toString());
        logger.exiting(className, "getState", value);
        lastKnownStatus = value.intValue();
        return lastKnownStatus;
      }
      catch (Exception e) {
        logger.throwing(className, "getState", e);
        if (lastKnownStatus != CIBOperationalStatusState.FAILED) {
          lastKnownStatus = CIBOperationalStatusState.FAILED;
          lastKnownChange = System.currentTimeMillis();
        }
        return lastKnownStatus;
      }
    }
    else {
      logger.finest(className + " State Provider not started");
      logger.exiting(className, "getState", new Long( -1));
      if (lastKnownStatus != CIBOperationalStatusState.FAILED) {
        lastKnownStatus = CIBOperationalStatusState.FAILED;
        lastKnownChange = System.currentTimeMillis();
      }
      return lastKnownStatus;
    }
  }

  /**
   * getStateString
   *
   * @return String
   */
  public String toStateString() throws CIBIOException,
      CIBAttributeNotFoundException {
    logger.entering(className, "toStateString");
    if (isStarted == true) {
      logger.finest(className + " State Provider started");
      logger.finest(className + " getAttribute OperationalState");
      int value = getState();
      String result = new String();
      switch (value) {
        case 0:
          result = STR_STARTING;
          break;
        case 1:
          result = STR_RUNNING;
          break;
        case 2:
          result = STR_STOPPING;
          break;
        case 3:
          result = STR_STOPPED;
          break;
        case 4:
          result = STR_FAILED;
          break;
        default:
          result = STR_FAILED;
      }
      logger.exiting(className, "toStateString", result);
      return result;
    }
    else {
      logger.finest(className + " State Provider not started");
      logger.exiting(className, "toStateString", null);
      return STR_FAILED;
    }
  }

  /**
   * getUpTime
   *
   * @return long
   */
  public long getStartTime() {
    logger.entering(className, "getStartTime");
    if (isStarted == true) {

      try {
        logger.finest(className + " State Provider started");
        logger.finest(className + " getAttribute RunningTime");
        Long value = new Long(myConnection.getAttribute("RunningTime").getValue().
                              toString());
        logger.exiting(className, "getStartTime", value);
        return value.longValue();
      }
      catch (Exception e) {
        logger.throwing(className, "getStartTime", e);
        return -1;
      }
    }
    else {
      logger.finest(className + " State Provider not started");
      logger.exiting(className, "getStartTime", new Long( -1));
      return -1;
    }
  }

  /**
   * Initialize the statistics 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 statistics and clean the statistics objects/values
   * when needed, close all the communications.
   */

  public void destroy() throws CIBIOException, CIBException {
    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.
   */

  public 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 statistics collections and clean the statistics objects/values
   * when needed, close all the communications.
   */

  public 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");
  }

  public String toString() {
    String result = new String("OperationalStatus:");
    try {
      result = result + "State=" + this.getState() + STR_SEPARATOR;
      result = result + "StateString=" + this.toStateString() + STR_SEPARATOR;
      result = result + "LastChange=" + this.getLastChange() + STR_SEPARATOR;
      result = result + "StartTime=" + this.getStartTime() + STR_SEPARATOR;
    }
    catch (Exception e) {
      logger.throwing(className, "toString", e);
      return null;
    }
    return result;
  }
}
