/*
 * 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.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
import java.util.List;

import javax.management.JMX;
import javax.management.MBeanException;
import javax.management.MBeanInfo;
import javax.management.MBeanNotificationInfo;
import javax.management.Notification;
import javax.management.NotificationBroadcaster;
import javax.management.NotificationBroadcasterSupport;
import javax.management.NotificationEmitter;
import javax.management.NotificationFilter;
import javax.management.NotificationListener;
import javax.management.ObjectName;

import org.apache.logging.log4j.Logger;

import org.apache.geode.SystemFailure;
import org.apache.geode.cache.Region;
import org.apache.geode.cache.execute.FunctionService;
import org.apache.geode.cache.execute.ResultCollector;
import org.apache.geode.distributed.DistributedMember;
import org.apache.geode.internal.logging.LogService;



/**
 * This class is the proxy handler for all the proxies created for federated MBeans. Its designed
 * with Java proxy mechanism. All data calls are delegated to the federation components. All method
 * calls are routed to specified members via Function service
 *
 *
 */

public class MBeanProxyInvocationHandler implements InvocationHandler {

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

  /**
   * Name of the MBean
   */
  private ObjectName objectName;

  /**
   * The monitoring region where this Object resides.
   */
  private Region<String, Object> monitoringRegion;

  /**
   * The member to which this proxy belongs
   */

  private DistributedMember member;


  /**
   * emitter is a helper class for sending notifications on behalf of the proxy
   */
  private final NotificationBroadcasterSupport emitter;

  private final ProxyInterface proxyImpl;

  private boolean isMXBean;

  private MXBeanProxyInvocationHandler mxbeanInvocationRef;



  /**
   *
   * @param member member to which this MBean belongs
   * @param monitoringRegion corresponding MonitoringRegion
   * @param objectName ObjectName of the MBean
   * @param interfaceClass on which interface the proxy to be exposed
   */
  public static Object newProxyInstance(DistributedMember member,
      Region<String, Object> monitoringRegion, ObjectName objectName,
      FederationComponent federationComponent, Class interfaceClass)
      throws ClassNotFoundException, IntrospectionException {
    boolean isMXBean = JMX.isMXBeanInterface(interfaceClass);
    boolean notificationBroadcaster = federationComponent.isNotificationEmitter();

    InvocationHandler handler =
        new MBeanProxyInvocationHandler(member, objectName, monitoringRegion, isMXBean);

    Class[] interfaces;

    if (notificationBroadcaster) {
      interfaces =
          new Class[] {interfaceClass, ProxyInterface.class, NotificationBroadCasterProxy.class};
    } else {
      interfaces = new Class[] {interfaceClass, ProxyInterface.class};
    }

    Object proxy = Proxy.newProxyInstance(MBeanProxyInvocationHandler.class.getClassLoader(),
        interfaces, handler);

    return interfaceClass.cast(proxy);
  }

  /**
   *
   * @param member member to which this MBean belongs
   * @param objectName ObjectName of the MBean
   * @param monitoringRegion corresponding MonitoringRegion
   */
  private MBeanProxyInvocationHandler(DistributedMember member, ObjectName objectName,
      Region<String, Object> monitoringRegion, boolean isMXBean)
      throws IntrospectionException, ClassNotFoundException {
    this.member = member;
    this.objectName = objectName;
    this.monitoringRegion = monitoringRegion;
    this.emitter = new NotificationBroadcasterSupport();
    this.proxyImpl = new ProxyInterfaceImpl();
    this.isMXBean = isMXBean;

  }

  /**
   * Inherited method from Invocation handler All object state requests are delegated to the
   * federated component.
   *
   * All setters and operations() are delegated to the function service.
   *
   * Notification emmitter methods are also delegated to the function service
   */
  @Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

    if (logger.isTraceEnabled()) {
      logger.trace("Invoking Method {}", method.getName());
    }
    final Class methodClass = method.getDeclaringClass();



    if (methodClass.equals(NotificationBroadcaster.class)
        || methodClass.equals(NotificationEmitter.class))
      return invokeBroadcasterMethod(proxy, method, args);

    final String methodName = method.getName();
    final Class[] paramTypes = method.getParameterTypes();
    final Class returnType = method.getReturnType();



    final int nargs = (args == null) ? 0 : args.length;

    if (methodName.equals("setLastRefreshedTime")) {
      proxyImpl.setLastRefreshedTime((Long) args[0]);
      return null;
    }
    if (methodName.equals("getLastRefreshedTime")) {
      return proxyImpl.getLastRefreshedTime();
    }

    if (methodName.equals("sendNotification")) {
      sendNotification(args[0]);
      return null;
    }

    // local or not: equals, toString, hashCode
    if (shouldDoLocally(proxy, method)) {
      return doLocally(proxy, method, args);
    }

    // Support For MXBean open types
    if (isMXBean) {
      MXBeanProxyInvocationHandler p = findMXBeanProxy(objectName, methodClass, this);
      return p.invoke(proxy, method, args);
    }

    if (methodName.startsWith("get") && methodName.length() > 3 && nargs == 0
        && !returnType.equals(Void.TYPE)) {
      return delegateToObjectState(methodName.substring(3));
    }

    if (methodName.startsWith("is") && methodName.length() > 2 && nargs == 0
        && (returnType.equals(Boolean.TYPE) || returnType.equals(Boolean.class))) {
      return delegateToObjectState(methodName.substring(2));
    }

    final String[] signature = new String[paramTypes.length];
    for (int i = 0; i < paramTypes.length; i++)
      signature[i] = paramTypes[i].getName();

    if (methodName.startsWith("set") && methodName.length() > 3 && nargs == 1
        && returnType.equals(Void.TYPE)) {
      return delegateToFucntionService(objectName, methodName, args, signature);

    }

    return delegateToFucntionService(objectName, methodName, args, signature);

  }



  /**
   * As this proxy may behave as an notification emitter it delegates to the member
   * NotificationBroadcasterSupport object
   *
   */
  private void sendNotification(Object notification) {
    emitter.sendNotification((Notification) notification);
  }

  /**
   * This will get the data from Object state which is replicated across the hidden region
   * FederataionComponent being the carrier.
   *
   */
  protected Object delegateToObjectState(String attributeName) throws Throwable {


    Object returnObj;
    try {
      FederationComponent fedComp =
          (FederationComponent) monitoringRegion.get(objectName.toString());
      returnObj = fedComp.getValue(attributeName);
    } catch (IllegalArgumentException e) {
      throw new MBeanException(e);
    } catch (Exception e) {
      throw new MBeanException(e);
    } catch (VirtualMachineError e) {
      SystemFailure.initiateFailure(e);
      throw e;
    } catch (Throwable th) {
      SystemFailure.checkFailure();
      throw new MBeanException(new Exception(th.getLocalizedMessage()));
    }
    return returnObj;
  }

  /**
   * It will call the Generic function to execute the method on the remote VM
   *
   * @param objectName ObjectName of the MBean
   * @param methodName method name
   * @param args arguments to the methods
   * @param signature signature of the method
   * @return result Object
   */
  protected Object delegateToFucntionService(ObjectName objectName, String methodName,
      Object[] args, String[] signature) throws Throwable {

    Object[] functionArgs = new Object[5];
    functionArgs[0] = objectName;
    functionArgs[1] = methodName;
    functionArgs[2] = signature;
    functionArgs[3] = args;
    functionArgs[4] = member.getName();
    List<Object> result = null;
    try {

      ResultCollector rc = FunctionService.onMember(member).setArguments(functionArgs)
          .execute(ManagementConstants.MGMT_FUNCTION_ID);
      result = (List<Object>) rc.getResult();
      // Exceptions of ManagementFunctions


    } catch (Exception e) {
      if (logger.isDebugEnabled()) {
        logger.debug(" Exception while Executing Funtion {}", e.getMessage(), e);
      }
      // Only in case of Exception caused for Function framework.
      return null;
    } catch (VirtualMachineError e) {
      SystemFailure.initiateFailure(e);
      throw e;
    } catch (Throwable th) {
      SystemFailure.checkFailure();
      if (logger.isDebugEnabled()) {
        logger.debug(" Exception while Executing Funtion {}", th.getMessage(), th);
      }
      return null;
    }

    return checkErrors(result.get(ManagementConstants.RESULT_INDEX));

  }

  private Object checkErrors(Object lastResult) throws Throwable {


    if (lastResult instanceof MBeanException) {
      // Convert all MBean public API exceptions to MBeanException
      throw (Exception) lastResult;
    }

    if (lastResult instanceof Exception) {
      return null;
    }
    if (lastResult instanceof Throwable) {
      return null;
    }
    return lastResult;
  }

  /**
   * The call will delegate to Managed Node for NotificationHub to register a local listener to
   * listen for notification from the MBean
   *
   * Moreover it will also add the client to local listener list by adding to the contained emitter.
   *
   * @param proxy the proxy object
   * @param method method to be invoked
   * @param args method arguments
   * @return result value if any
   */
  private Object invokeBroadcasterMethod(Object proxy, Method method, Object[] args)
      throws Throwable {
    final String methodName = method.getName();
    final int nargs = (args == null) ? 0 : args.length;

    final Class[] paramTypes = method.getParameterTypes();
    final String[] signature = new String[paramTypes.length];

    if (methodName.equals("addNotificationListener")) {

      /*
       * The various throws of IllegalArgumentException here should not happen, since we know what
       * the methods in NotificationBroadcaster and NotificationEmitter are.
       */

      if (nargs != 3) {
        final String msg = "Bad arg count to addNotificationListener: " + nargs;
        throw new IllegalArgumentException(msg);
      }
      /*
       * Other inconsistencies will produce ClassCastException below.
       */

      NotificationListener listener = (NotificationListener) args[0];
      NotificationFilter filter = (NotificationFilter) args[1];
      Object handback = args[2];
      emitter.addNotificationListener(listener, filter, handback);
      delegateToFucntionService(objectName, methodName, null, signature);
      return null;

    } else if (methodName.equals("removeNotificationListener")) {
      /*
       * NullPointerException if method with no args, but that shouldn't happen because removeNL
       * does have args.
       */
      NotificationListener listener = (NotificationListener) args[0];

      switch (nargs) {
        case 1:
          emitter.removeNotificationListener(listener);
          /**
           * No need to send listener and filter details to other members. We only need to send a
           * message saying remove the listner registered for this object on your side. Fixes Bug[
           * #47075 ]
           */
          delegateToFucntionService(objectName, methodName, null, signature);
          return null;

        case 3:
          NotificationFilter filter = (NotificationFilter) args[1];
          Object handback = args[2];
          emitter.removeNotificationListener(listener, filter, handback);

          delegateToFucntionService(objectName, methodName, null, signature);
          return null;

        default:
          final String msg = "Bad arg count to removeNotificationListener: " + nargs;
          throw new IllegalArgumentException(msg);
      }

    } else if (methodName.equals("getNotificationInfo")) {

      if (args != null) {
        throw new IllegalArgumentException("getNotificationInfo has " + "args");
      }

      if (!MBeanJMXAdapter.mbeanServer.isRegistered(objectName)) {
        return new MBeanNotificationInfo[0];
      }

      /**
       * MBean info is delegated to function service as intention is to get the info of the actual
       * mbean rather than the proxy
       */


      Object obj = delegateToFucntionService(objectName, methodName, args, signature);
      if (obj instanceof String) {
        return new MBeanNotificationInfo[0];
      }
      MBeanInfo info = (MBeanInfo) obj;
      return info.getNotifications();

    } else {
      throw new IllegalArgumentException("Bad method name: " + methodName);
    }
  }



  /**
   * Internal implementation of all the generic proxy methods
   *
   *
   */
  private class ProxyInterfaceImpl implements ProxyInterface {
    /**
     * last refreshed time of the proxy
     */
    private long lastRefreshedTime;

    /**
     * Constructore
     */
    public ProxyInterfaceImpl() {
      this.lastRefreshedTime = System.currentTimeMillis();
    }

    /**
     * Last refreshed time
     */
    @Override
    public long getLastRefreshedTime() {
      return lastRefreshedTime;
    }

    /**
     * sets the proxy refresh time
     */
    @Override
    public void setLastRefreshedTime(long lastRefreshedTime) {
      this.lastRefreshedTime = lastRefreshedTime;
    }

  }

  private boolean shouldDoLocally(Object proxy, Method method) {
    final String methodName = method.getName();
    if ((methodName.equals("hashCode") || methodName.equals("toString"))
        && method.getParameterTypes().length == 0)
      return true;
    if (methodName.equals("equals")
        && Arrays.equals(method.getParameterTypes(), new Class[] {Object.class}))
      return true;
    return false;
  }

  private Object doLocally(Object proxy, Method method, Object[] args) {
    final String methodName = method.getName();
    FederationComponent fedComp = (FederationComponent) monitoringRegion.get(objectName.toString());
    if (methodName.equals("equals")) {

      return fedComp.equals(args[0]);

    } else if (methodName.equals("toString")) {
      return fedComp.toString();
    } else if (methodName.equals("hashCode")) {
      return fedComp.hashCode();
    }

    throw new RuntimeException("Unexpected method name: " + methodName);
  }

  private MXBeanProxyInvocationHandler findMXBeanProxy(ObjectName objectName,
      Class<?> mxbeanInterface, MBeanProxyInvocationHandler handler) throws Throwable {
    MXBeanProxyInvocationHandler proxyRef = mxbeanInvocationRef;

    if (mxbeanInvocationRef == null) {
      synchronized (this) {
        try {
          mxbeanInvocationRef =
              new MXBeanProxyInvocationHandler(objectName, mxbeanInterface, handler);
        } catch (IllegalArgumentException e) {
          String msg =
              "Cannot make MXBean proxy for " + mxbeanInterface.getName() + ": " + e.getMessage();
          throw new IllegalArgumentException(msg, e.getCause());
        }

      }

    }
    return mxbeanInvocationRef;
  }

}
