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

import java.beans.IntrospectionException;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import javax.management.InstanceNotFoundException;
import javax.management.ObjectName;

import org.apache.logging.log4j.Logger;

import org.apache.geode.cache.EntryNotFoundException;
import org.apache.geode.cache.Region;
import org.apache.geode.distributed.DistributedMember;
import org.apache.geode.internal.ClassLoadUtil;
import org.apache.geode.internal.logging.LogService;
import org.apache.geode.management.ManagementException;

/**
 * Instance of this class is responsible for proxy creation/deletion etc.
 *
 * If a member is added/removed proxy factory is responsible for creating removing the corresponding
 * proxies for that member.
 *
 * It also maintains a proxy repository {@link MBeanProxyInfoRepository} for quick access to the
 * proxy instances
 */
public class MBeanProxyFactory {
  private static final Logger logger = LogService.getLogger();

  /**
   * Proxy repository contains several indexes to search proxies in an efficient manner.
   */
  private MBeanProxyInfoRepository proxyRepo;


  /**
   * Interface between GemFire federation layer and Java JMX layer
   */
  private MBeanJMXAdapter jmxAdapter;

  private SystemManagementService service;

  /**
   * @param jmxAdapter adapter to interface between JMX and GemFire
   * @param service management service
   */
  public MBeanProxyFactory(MBeanJMXAdapter jmxAdapter, SystemManagementService service) {

    this.jmxAdapter = jmxAdapter;
    this.proxyRepo = new MBeanProxyInfoRepository();
    this.service = service;
  }

  /**
   * Creates a single proxy and adds a {@link ProxyInfo} to proxy repository
   * {@link MBeanProxyInfoRepository}
   *
   * @param member {@link org.apache.geode.distributed.DistributedMember}
   * @param objectName {@link javax.management.ObjectName} of the Bean
   * @param monitoringRegion monitoring region containing the proxies
   */
  public void createProxy(DistributedMember member, ObjectName objectName,
      Region<String, Object> monitoringRegion, Object newVal) {

    try {
      FederationComponent federationComponent = (FederationComponent) newVal;
      String interfaceClassName = federationComponent.getMBeanInterfaceClass();

      Class interfaceClass = ClassLoadUtil.classFromName(interfaceClassName);

      Object object = MBeanProxyInvocationHandler.newProxyInstance(member, monitoringRegion,
          objectName, federationComponent, interfaceClass);

      jmxAdapter.registerMBeanProxy(object, objectName);

      if (logger.isDebugEnabled()) {
        logger.debug("Registered ObjectName : {}", objectName);
      }

      ProxyInfo proxyInfo = new ProxyInfo(interfaceClass, object, objectName);
      proxyRepo.addProxyToRepository(member, proxyInfo);

      service.afterCreateProxy(objectName, interfaceClass, object, (FederationComponent) newVal);

      if (logger.isDebugEnabled()) {
        logger.debug("Proxy Created for : {}", objectName);
      }

    } catch (ClassNotFoundException | IntrospectionException e) {
      throw new ManagementException(e);
    }

  }

  /**
   * This method will create all the proxies for a given DistributedMember. It does not throw any
   * exception to its caller. It handles the error and logs error messages
   *
   * It will be called from GII or when a member joins the system
   *
   * @param member {@link org.apache.geode.distributed.DistributedMember}
   * @param monitoringRegion monitoring region containing the proxies
   */
  public void createAllProxies(DistributedMember member, Region<String, Object> monitoringRegion) {

    if (logger.isDebugEnabled()) {
      logger.debug("Creating proxy for: {}", member.getId());
    }

    Set<Map.Entry<String, Object>> mbeans = monitoringRegion.entrySet();

    for (Map.Entry<String, Object> mbean : mbeans) {

      ObjectName objectName = null;
      try {
        objectName = ObjectName.getInstance(mbean.getKey());
        if (logger.isDebugEnabled()) {
          logger.debug("Creating proxy for ObjectName: " + objectName.toString());
        }

        createProxy(member, objectName, monitoringRegion, mbean.getValue());
      } catch (Exception e) {
        logger.warn("Create Proxy failed for {} with exception {}", objectName, e.getMessage(), e);
      }

    }
  }

  /**
   * Removes all proxies for a given member
   *
   * @param member {@link org.apache.geode.distributed.DistributedMember}
   * @param monitoringRegion monitoring region containing the proxies
   */
  public void removeAllProxies(DistributedMember member, Region<String, Object> monitoringRegion) {

    Set<Entry<String, Object>> entries = monitoringRegion.entrySet();

    if (logger.isDebugEnabled()) {
      logger.debug("Removing {} proxies for member {}", entries.size(), member.getId());
    }

    for (Entry<String, Object> entry : entries) {
      String key = null;
      Object val;
      try {
        key = entry.getKey();// MBean Name in String format.
        val = entry.getValue(); // Federation Component
        ObjectName mbeanName = ObjectName.getInstance(key);
        removeProxy(member, mbeanName, val);
      } catch (EntryNotFoundException entryNotFoundException) {
        // Entry has already been removed by another thread, so no need to remove it
        logProxyAlreadyRemoved(member, entry);
      } catch (Exception e) {
        if (!(e.getCause() instanceof InstanceNotFoundException)) {
          logger.warn("Remove Proxy failed for {} due to {}", key, e.getMessage(), e);
        }
      }
    }
  }

  /**
   * Removes the proxy
   *
   * @param member {@link org.apache.geode.distributed.DistributedMember}
   * @param objectName {@link javax.management.ObjectName} of the Bean
   */
  public void removeProxy(DistributedMember member, ObjectName objectName, Object oldVal) {

    try {
      if (logger.isDebugEnabled()) {
        logger.debug("Removing proxy for ObjectName: {}", objectName);

      }

      ProxyInfo proxyInfo = proxyRepo.findProxyInfo(objectName);
      proxyRepo.removeProxy(member, objectName);
      if (proxyInfo != null) {
        service.afterRemoveProxy(objectName, proxyInfo.getProxyInterface(),
            proxyInfo.getProxyInstance(), (FederationComponent) oldVal);
      }
      jmxAdapter.unregisterMBean(objectName);

      if (logger.isDebugEnabled()) {
        logger.debug("Removed proxy for ObjectName: {}", objectName);
      }

    } catch (Exception e) {
      if (!(e.getCause() instanceof InstanceNotFoundException)) {
        logger.warn("Could not remove proxy for Member {} due to {}", member, e.getMessage(), e);
      }
    }
  }

  public void updateProxy(ObjectName objectName, ProxyInfo proxyInfo, Object newObject,
      Object oldObject) {
    try {
      if (proxyInfo != null) {
        Class interfaceClass = proxyInfo.getProxyInterface();
        service.afterUpdateProxy(objectName, interfaceClass, proxyInfo.getProxyInstance(),
            (FederationComponent) newObject, (FederationComponent) oldObject);
      }
    } catch (Exception e) {
      throw new ManagementException(e);
    }
  }

  /**
   * Find a particular proxy instance for a {@link javax.management.ObjectName} ,
   * {@link org.apache.geode.distributed.DistributedMember} and interface class If the proxy
   * interface does not implement the given interface class a {@link java.lang.ClassCastException}.
   * will be thrown
   *
   * @param objectName {@link javax.management.ObjectName} of the MBean
   * @param interfaceClass interface class implemented by proxy
   * @return an instance of proxy exposing the given interface
   */
  public <T> T findProxy(ObjectName objectName, Class<T> interfaceClass) {

    return proxyRepo.findProxyByName(objectName, interfaceClass);


  }

  public ProxyInfo findProxyInfo(ObjectName objectName) {
    return proxyRepo.findProxyInfo(objectName);
  }

  /**
   * Find a set of proxies given a {@link org.apache.geode.distributed.DistributedMember}
   *
   * @param member {@link org.apache.geode.distributed.DistributedMember}
   * @return a set of {@link javax.management.ObjectName}
   */
  public Set<ObjectName> findAllProxies(DistributedMember member) {

    return proxyRepo.findProxySet(member);

  }

  /**
   * This will return the last updated time of the proxyMBean
   *
   * @param objectName {@link javax.management.ObjectName} of the MBean
   * @return last updated time of the proxy
   */
  public long getLastUpdateTime(ObjectName objectName) {

    ProxyInterface proxyObj = findProxy(objectName, ProxyInterface.class);

    return proxyObj.getLastRefreshedTime();

  }

  void logProxyAlreadyRemoved(DistributedMember member, Entry<String, Object> entry) {
    logger.warn("Proxy for entry {} and member {} has already been removed", entry,
        member.getId());
  }

}
