/*
 * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
 * agreements. See the NOTICE file distributed with this work for additional information regarding
 * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance with the License. You may obtain a
 * copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */
package org.apache.geode.admin.jmx.internal;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import javax.management.MalformedObjectNameException;
import javax.management.Notification;
import javax.management.ObjectName;
import javax.management.modelmbean.ModelMBean;
import javax.naming.OperationNotSupportedException;

import org.apache.commons.modeler.ManagedBean;
import org.apache.logging.log4j.Logger;

import org.apache.geode.admin.AdminException;
import org.apache.geode.admin.CacheServerConfig;
import org.apache.geode.admin.CacheVmConfig;
import org.apache.geode.admin.ConfigurationParameter;
import org.apache.geode.admin.StatisticResource;
import org.apache.geode.admin.SystemMemberCache;
import org.apache.geode.admin.SystemMemberCacheEvent;
import org.apache.geode.admin.SystemMemberRegionEvent;
import org.apache.geode.admin.internal.CacheServerImpl;
import org.apache.geode.admin.internal.ConfigurationParameterImpl;
import org.apache.geode.internal.admin.ClientMembershipMessage;
import org.apache.geode.internal.admin.GemFireVM;
import org.apache.geode.internal.admin.StatResource;
import org.apache.geode.logging.internal.log4j.api.LogService;

/**
 * MBean representation of a {@link org.apache.geode.admin.CacheVm}.
 *
 * @since GemFire 4.0
 */
public class CacheServerJmxImpl extends CacheServerImpl
    implements ManagedResource, CacheVmConfig, CacheServerConfig, SystemMemberJmx {

  private static final Logger logger = LogService.getLogger();

  /**
   * Interval in seconds between refreshes. Value less than one results in no refreshing
   */
  private int refreshInterval = 0;

  /** The object name of this managed resource */
  private ObjectName objectName;

  /** The name of the MBean that will manage this resource */
  private String mbeanName;

  /** The ModelMBean that is configured to manage this resource */
  private ModelMBean modelMBean;

  /** Reference to the cache MBean representing a Cache in the Cache VM Member */
  private SystemMemberCacheJmxImpl managedSystemMemberCache;

  /** collection to collect all the resources created for this member */
  private Map<StatResource, StatisticResourceJmxImpl> managedStatisticsResourcesMap =
      new HashMap<StatResource, StatisticResourceJmxImpl>();

  ////////////////////// Constructors //////////////////////

  /**
   * Creates a new <code>CacheServerJmxImpl</code> for an existing cache server.
   */
  CacheServerJmxImpl(AdminDistributedSystemJmxImpl system, GemFireVM vm) throws AdminException {

    super(system, vm);
    initializeMBean();
  }

  /**
   * Creates a new <code>CacheServerJmxImpl</code> for an newly-created cache server.
   */
  CacheServerJmxImpl(AdminDistributedSystemJmxImpl system, CacheVmConfig config)
      throws AdminException {

    super(system, config);
    initializeMBean();
  }

  ////////////////////// Instance Methods //////////////////////

  /**
   * Creates and registers the MBean to manage this resource
   */
  private void initializeMBean() throws AdminException {
    this.mbeanName = new StringBuffer("GemFire.CacheVm:").append("id=")
        .append(MBeanUtil.makeCompliantMBeanNameProperty(getId())).append(",type=")
        .append(MBeanUtil.makeCompliantMBeanNameProperty(getType().getName())).toString();

    this.objectName =
        MBeanUtil.createMBean(this, addDynamicAttributes(MBeanUtil.lookupManagedBean(this)));

    // Refresh Interval
    AdminDistributedSystemJmxImpl sysJmx = (AdminDistributedSystemJmxImpl) system;
    if (sysJmx.getRefreshInterval() > 0)
      this.refreshInterval = sysJmx.getRefreshInterval();
  }

  @Override
  public String getMBeanName() {
    return this.mbeanName;
  }

  @Override
  public ModelMBean getModelMBean() {
    return this.modelMBean;
  }

  @Override
  public void setModelMBean(ModelMBean modelMBean) {
    this.modelMBean = modelMBean;
  }

  @Override
  public ObjectName getObjectName() {
    return this.objectName;
  }

  @Override
  public ManagedResourceType getManagedResourceType() {
    return ManagedResourceType.CACHE_VM;
  }

  /**
   * Un-registers all the statistics & cache managed resource created for this member. After
   * un-registering the resource MBean instances, clears managedStatisticsResourcesMap collection &
   * sets managedSystemMemberCache to null.
   *
   * Creates ConfigurationParameterJmxImpl, StatisticResourceJmxImpl and SystemMemberCacheJmxImpl.
   * But cleans up only StatisticResourceJmxImpl and SystemMemberCacheJmxImpl which are of type
   * ManagedResource.
   */
  @Override
  public void cleanupResource() {
    synchronized (this.managedStatisticsResourcesMap) {
      ConfigurationParameter[] names = getConfiguration();
      if (names != null) {
        for (int i = 0; i < names.length; i++) {
          ConfigurationParameter parm = names[i];
          ((ConfigurationParameterImpl) parm).removeConfigurationParameterListener(this);
        }
      }
      this.parms.clear();

      Collection<StatisticResourceJmxImpl> statisticResources =
          managedStatisticsResourcesMap.values();

      for (StatisticResourceJmxImpl statisticResource : statisticResources) {
        MBeanUtil.unregisterMBean(statisticResource);
      }

      this.managedStatisticsResourcesMap.clear();
    }

    MBeanUtil.unregisterMBean(this.managedSystemMemberCache);
    this.managedSystemMemberCache = null;
  }

  /////////////////////// Configuration ///////////////////////

  @Override
  public String getHost() {
    return this.getConfig().getHost();
  }

  @Override
  public void setHost(String host) {
    this.getConfig().setHost(host);
  }

  @Override
  public String getWorkingDirectory() {
    return this.getConfig().getWorkingDirectory();
  }

  @Override
  public void setWorkingDirectory(String dir) {
    this.getConfig().setWorkingDirectory(dir);
  }

  @Override
  public String getProductDirectory() {
    return this.getConfig().getProductDirectory();
  }

  @Override
  public void setProductDirectory(String dir) {
    this.getConfig().setProductDirectory(dir);
  }

  @Override
  public String getRemoteCommand() {
    return this.getConfig().getRemoteCommand();
  }

  @Override
  public void setRemoteCommand(String remoteCommand) {
    this.getConfig().setRemoteCommand(remoteCommand);
  }

  @Override
  public void validate() {
    throw new UnsupportedOperationException("Should not be invoked");
  }

  @Override
  public Object clone() throws CloneNotSupportedException {
    throw new UnsupportedOperationException("Should not be invoked");
  }

  @Override
  public String getCacheXMLFile() {
    return this.getConfig().getCacheXMLFile();
  }

  @Override
  public void setCacheXMLFile(String cacheXMLFile) {
    this.getConfig().setCacheXMLFile(cacheXMLFile);
  }

  @Override
  public String getClassPath() {
    return this.getConfig().getClassPath();
  }

  @Override
  public void setClassPath(String classpath) {
    this.getConfig().setClassPath(classpath);
  }

  // -------------------------------------------------------------------------
  // MBean attribute accessors/mutators
  // -------------------------------------------------------------------------

  /**
   * Gets the interval in seconds between config refreshes
   *
   * @return the current refresh interval in seconds
   */
  @Override
  public int getRefreshInterval() {
    return this.refreshInterval;
  }

  /**
   * Sets interval in seconds between cache config refreshes; zero or less turns off auto
   * refreshing. Manual refreshing has no effect on when the next scheduled refresh will occur.
   *
   * @param refreshInterval the new refresh interval in seconds
   */
  @Override
  public void _setRefreshInterval(int refreshInterval) {
    boolean isRegistered = MBeanUtil.isRefreshNotificationRegistered(this,
        RefreshNotificationType.SYSTEM_MEMBER_CONFIG);

    if (isRegistered && (getRefreshInterval() == refreshInterval))
      return;

    this.refreshInterval = Helper.setAndReturnRefreshInterval(this, refreshInterval);
  }

  /**
   * RefreshInterval is now set only through the AdminDistributedSystem property refreshInterval.
   * Attempt to set refreshInterval on CacheServerJmx MBean would result in an
   * OperationNotSupportedException Auto-refresh is enabled on demand when a call to refreshConfig
   * is made
   *
   * @param refreshInterval the new refresh interval in seconds
   * @deprecated since 6.0 use DistributedSystemConfig.refreshInterval instead
   */
  @Override
  @Deprecated
  public void setRefreshInterval(int refreshInterval) throws OperationNotSupportedException {
    throw new OperationNotSupportedException(
        "RefreshInterval can not be set directly. Use DistributedSystemConfig.refreshInterval.");
  }

  // -------------------------------------------------------------------------
  // MBean Operations
  // -------------------------------------------------------------------------

  @Override
  public void refreshConfig() throws org.apache.geode.admin.AdminException {
    // 1st call to refreshConfig would trigger
    // the auto-refresh if an interval is set
    if (this.refreshInterval > 0) {
      this._setRefreshInterval(this.refreshInterval);
    }

    super.refreshConfig();
  }

  /**
   * Gets this member's cache.
   *
   * @return array of ObjectName for this member's cache
   */
  @Override
  public ObjectName manageCache() throws AdminException, MalformedObjectNameException {
    return Helper.manageCache(this);
  }

  /**
   * Gets all active StatisticResources for this manager.
   *
   * @return array of ObjectName instances
   */
  @Override
  public ObjectName[] manageStats() throws AdminException, MalformedObjectNameException {
    return Helper.manageStats(this);
  }

  /**
   * Gets the active StatisticResources for this manager, based on the typeName as the key
   *
   * @return ObjectName of StatisticResourceJMX instance
   */
  @Override
  public ObjectName[] manageStat(String statisticsTypeName)
      throws AdminException, MalformedObjectNameException {

    return Helper.manageStat(this, statisticsTypeName);
  }

  // -------------------------------------------------------------------------
  // JMX Notification listener
  // -------------------------------------------------------------------------

  /**
   * Handles notification to refresh. Reacts by refreshing the values of this GemFireManager's
   * ConfigurationParamaters. Any other notification is ignored. Given notification is handled only
   * if there is any JMX client connected to the system.
   *
   * @param notification the JMX notification being received
   * @param hb handback object is unused
   */
  @Override
  public void handleNotification(Notification notification, Object hb) {
    AdminDistributedSystemJmxImpl systemJmx = (AdminDistributedSystemJmxImpl) this.system;

    if (!systemJmx.isRmiClientCountZero()) {
      Helper.handleNotification(this, notification, hb);
    }
  }

  // -------------------------------------------------------------------------
  // Template methods overriden from superclass...
  // -------------------------------------------------------------------------

  /**
   * Template method for creating instance of ConfigurationParameter. Overridden to return
   * ConfigurationParameterJmxImpl.
   */
  @Override
  protected ConfigurationParameter createConfigurationParameter(String name, String description,
      Object value, Class type, boolean userModifiable) {
    return new ConfigurationParameterJmxImpl(name, description, value, type, userModifiable);
  }



  /**
   * Override createStatisticResource by instantiating StatisticResourceJmxImpl if it was not
   * created earlier otherwise returns the same instance.
   *
   * @param stat StatResource reference for which this JMX resource is to be created
   * @return StatisticResourceJmxImpl - JMX Implementation of StatisticResource
   * @throws AdminException if constructing StatisticResourceJmxImpl instance fails
   */
  @Override
  protected StatisticResource createStatisticResource(StatResource stat)
      throws org.apache.geode.admin.AdminException {
    StatisticResourceJmxImpl managedStatisticResource = null;

    synchronized (this.managedStatisticsResourcesMap) {
      /*
       * Ensuring that a single instance of Statistic Resource is created per StatResource.
       */
      StatisticResourceJmxImpl statisticResourceJmxImpl = managedStatisticsResourcesMap.get(stat);
      if (statisticResourceJmxImpl != null) {
        managedStatisticResource = statisticResourceJmxImpl;
      } else {
        managedStatisticResource = new StatisticResourceJmxImpl(stat, this);
        managedStatisticResource.getStatistics();// inits timer
        managedStatisticsResourcesMap.put(stat, managedStatisticResource);
      }
    }
    return managedStatisticResource;
  }

  /**
   * Override createSystemMemberCache by instantiating SystemMemberCacheJmxImpl if it was not
   * created earlier.
   *
   * @param vm GemFireVM reference for which this JMX resource is to be created
   * @return SystemMemberCacheJmxImpl - JMX Implementation of SystemMemberCache
   * @throws AdminException if constructing SystemMemberCacheJmxImpl instance fails
   */
  @Override
  protected SystemMemberCache createSystemMemberCache(GemFireVM vm)
      throws org.apache.geode.admin.AdminException {
    if (managedSystemMemberCache == null) {
      managedSystemMemberCache = new SystemMemberCacheJmxImpl(vm);
    }
    return managedSystemMemberCache;
  }

  // -------------------------------------------------------------------------
  // Create MBean attributes for each ConfigurationParameter
  // -------------------------------------------------------------------------

  /**
   * Add MBean attribute definitions for each ConfigurationParameter.
   *
   * @param managed the mbean definition to add attributes to
   * @return a new instance of ManagedBean copied from <code>managed</code> but with the new
   *         attributes added
   */
  @Override
  public ManagedBean addDynamicAttributes(ManagedBean managed)
      throws org.apache.geode.admin.AdminException {
    return Helper.addDynamicAttributes(this, managed);
  }

  /**
   * Cleans up Managed Resources created for the client that was connected to the server represented
   * by this class.
   *
   * @param clientId id of the client to be removed
   * @return List of ManagedResources associated with the client of given client id
   */
  /*
   * This clean up is for the clients. The clients are started with a loner DM. Hence the clientId
   * is not supposed to contain '/' as per InternalDistributedMember.toString().
   */
  public List<ManagedResource> cleanupBridgeClientResources(String clientId) {
    List<ManagedResource> returnedResources = new ArrayList<ManagedResource>();

    String compatibleId = "id_" + MBeanUtil.makeCompliantMBeanNameProperty(clientId);
    synchronized (this.managedStatisticsResourcesMap) {
      Set<Entry<StatResource, StatisticResourceJmxImpl>> entrySet =
          this.managedStatisticsResourcesMap.entrySet();

      for (Iterator<Entry<StatResource, StatisticResourceJmxImpl>> it = entrySet.iterator(); it
          .hasNext();) {
        Entry<StatResource, StatisticResourceJmxImpl> entry = it.next();
        StatisticResourceJmxImpl resource = entry.getValue();
        if (resource.getMBeanName().contains(compatibleId)) {
          it.remove(); // remove matching entry
          returnedResources.add(resource);
        }
      }
    }
    return returnedResources;
  }

  /**
   * Implementation handles client membership changes.
   *
   * @param clientId id of the client for whom membership change happened
   * @param eventType membership change type; one of {@link ClientMembershipMessage#JOINED},
   *        {@link ClientMembershipMessage#LEFT}, {@link ClientMembershipMessage#CRASHED}
   */
  @Override
  public void handleClientMembership(String clientId, int eventType) {
    String notifType = null;
    List<ManagedResource> cleanedUp = null;

    if (eventType == ClientMembershipMessage.LEFT) {
      notifType = NOTIF_CLIENT_LEFT;
      cleanedUp = cleanupBridgeClientResources(clientId);
    } else if (eventType == ClientMembershipMessage.CRASHED) {
      notifType = NOTIF_CLIENT_CRASHED;
      cleanedUp = cleanupBridgeClientResources(clientId);
    } else if (eventType == ClientMembershipMessage.JOINED) {
      notifType = NOTIF_CLIENT_JOINED;
    }

    if (cleanedUp != null) {
      for (ManagedResource resource : cleanedUp) {
        MBeanUtil.unregisterMBean(resource);
      }
    }

    Helper.sendNotification(this, new Notification(notifType, this.modelMBean,
        Helper.getNextNotificationSequenceNumber(), clientId));
  }

  /**
   * Implementation handles creation of cache by extracting the details from the given event object
   * and sending the {@link SystemMemberJmx#NOTIF_CACHE_CREATED} notification to the connected JMX
   * Clients.
   *
   * @param event event object corresponding to the creation of the cache
   */
  @Override
  public void handleCacheCreate(SystemMemberCacheEvent event) {
    Helper.sendNotification(this, new Notification(NOTIF_CACHE_CREATED, this.modelMBean,
        Helper.getNextNotificationSequenceNumber(), Helper.getCacheEventDetails(event)));
  }

  /**
   * Implementation handles closure of cache by extracting the details from the given event object
   * and sending the {@link SystemMemberJmx#NOTIF_CACHE_CLOSED} notification to the connected JMX
   * Clients.
   *
   * @param event event object corresponding to the closure of the cache
   */
  @Override
  public void handleCacheClose(SystemMemberCacheEvent event) {
    Helper.sendNotification(this, new Notification(NOTIF_CACHE_CLOSED, this.modelMBean,
        Helper.getNextNotificationSequenceNumber(), Helper.getCacheEventDetails(event)));
  }

  /**
   * Implementation handles creation of region by extracting the details from the given event object
   * and sending the {@link SystemMemberJmx#NOTIF_REGION_CREATED} notification to the connected JMX
   * Clients. Region Path is set as User Data in Notification.
   *
   * @param event event object corresponding to the creation of a region
   */
  @Override
  public void handleRegionCreate(SystemMemberRegionEvent event) {
    Notification notification = new Notification(NOTIF_REGION_CREATED, this.modelMBean,
        Helper.getNextNotificationSequenceNumber(), Helper.getRegionEventDetails(event));

    notification.setUserData(event.getRegionPath());

    Helper.sendNotification(this, notification);
  }

  /**
   * Implementation should handle loss of region by extracting the details from the given event
   * object and sending the {@link SystemMemberJmx#NOTIF_REGION_LOST} notification to the connected
   * JMX Clients. Region Path is set as User Data in Notification. Additionally, it also clears the
   * ManagedResources created for the region that is lost.
   *
   * @param event event object corresponding to the loss of a region
   */
  @Override
  public void handleRegionLoss(SystemMemberRegionEvent event) {
    SystemMemberCacheJmxImpl cacheResource = this.managedSystemMemberCache;

    if (cacheResource != null) {
      ManagedResource cleanedUp = cacheResource.cleanupRegionResources(event.getRegionPath());

      if (cleanedUp != null) {
        MBeanUtil.unregisterMBean(cleanedUp);
      }
    }

    Notification notification = new Notification(NOTIF_REGION_LOST, this.modelMBean,
        Helper.getNextNotificationSequenceNumber(), Helper.getRegionEventDetails(event));

    notification.setUserData(event.getRegionPath());

    Helper.sendNotification(this, notification);
  }
}
