/**
 *
 * 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.hadoop.hbase.util;

import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.nio.charset.Charset;

import org.apache.yetus.audience.InterfaceAudience;
import org.slf4j.Logger;

import edu.umd.cs.findbugs.annotations.NonNull;

@InterfaceAudience.Private
public class ReflectionUtils {
  @SuppressWarnings("unchecked")
  public static <T> T instantiateWithCustomCtor(String className,
      Class<? >[] ctorArgTypes, Object[] ctorArgs) {
    try {
      Class<? extends T> resultType = (Class<? extends T>) Class.forName(className);
      Constructor<? extends T> ctor = resultType.getDeclaredConstructor(ctorArgTypes);
      return instantiate(className, ctor, ctorArgs);
    } catch (ClassNotFoundException e) {
      throw new UnsupportedOperationException(
          "Unable to find " + className, e);
    } catch (NoSuchMethodException e) {
      throw new UnsupportedOperationException(
          "Unable to find suitable constructor for class " + className, e);
    }
  }

  public static <T> T instantiate(final String className, Constructor<T> ctor, Object... ctorArgs) {
    try {
      ctor.setAccessible(true);
      return ctor.newInstance(ctorArgs);
    } catch (IllegalAccessException e) {
      throw new UnsupportedOperationException(
          "Unable to access specified class " + className, e);
    } catch (InstantiationException e) {
      throw new UnsupportedOperationException(
          "Unable to instantiate specified class " + className, e);
    } catch (InvocationTargetException e) {
      throw new UnsupportedOperationException(
          "Constructor threw an exception for " + className, e);
    }
  }

  public static <T> T newInstance(Class<T> type, Object... params) {
    return instantiate(type.getName(), findConstructor(type, params), params);
  }

  @SuppressWarnings("unchecked")
  public static <T> Constructor<T> findConstructor(Class<T> type, Object... paramTypes) {
    Constructor<T>[] constructors = (Constructor<T>[]) type.getDeclaredConstructors();
    for (Constructor<T> ctor : constructors) {
      Class<?>[] ctorParamTypes = ctor.getParameterTypes();
      if (ctorParamTypes.length != paramTypes.length) {
        continue;
      }

      boolean match = true;
      for (int i = 0; i < ctorParamTypes.length && match; ++i) {
        if (paramTypes[i] == null) {
          match = !ctorParamTypes[i].isPrimitive();
        } else {
          Class<?> paramType = paramTypes[i].getClass();
          match = (!ctorParamTypes[i].isPrimitive()) ? ctorParamTypes[i].isAssignableFrom(paramType)
            : ((int.class.equals(ctorParamTypes[i]) && Integer.class.equals(paramType)) ||
              (long.class.equals(ctorParamTypes[i]) && Long.class.equals(paramType)) ||
              (double.class.equals(ctorParamTypes[i]) && Double.class.equals(paramType)) ||
              (char.class.equals(ctorParamTypes[i]) && Character.class.equals(paramType)) ||
              (short.class.equals(ctorParamTypes[i]) && Short.class.equals(paramType)) ||
              (boolean.class.equals(ctorParamTypes[i]) && Boolean.class.equals(paramType)) ||
              (byte.class.equals(ctorParamTypes[i]) && Byte.class.equals(paramType)));
        }
      }

      if (match) {
        return ctor;
      }
    }
    throw new UnsupportedOperationException(
      "Unable to find suitable constructor for class " + type.getName());
  }

  /* synchronized on ReflectionUtils.class */
  private static long previousLogTime = 0;
  private static final ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();

  /**
   * Log the current thread stacks at INFO level.
   * @param log the logger that logs the stack trace
   * @param title a descriptive title for the call stacks
   * @param minInterval the minimum time from the last
   */
  public static void logThreadInfo(Logger log,
                                   String title,
                                   long minInterval) {
    boolean dumpStack = false;
    if (log.isInfoEnabled()) {
      synchronized (ReflectionUtils.class) {
        long now = System.currentTimeMillis();
        if (now - previousLogTime >= minInterval * 1000) {
          previousLogTime = now;
          dumpStack = true;
        }
      }
      if (dumpStack) {
        try {
          ByteArrayOutputStream buffer = new ByteArrayOutputStream();
          printThreadInfo(new PrintStream(buffer, false, "UTF-8"), title);
          log.info(buffer.toString(Charset.defaultCharset().name()));
        } catch (UnsupportedEncodingException ignored) {
          log.warn("Could not write thread info about '" + title +
              "' due to a string encoding issue.");
        }
      }
    }
  }

  /**
   * Print all of the thread's information and stack traces.
   *
   * @param stream the stream to
   * @param title a string title for the stack trace
   */
  private static void printThreadInfo(PrintStream stream,
                                     String title) {
    final int STACK_DEPTH = 20;
    boolean contention = threadBean.isThreadContentionMonitoringEnabled();
    long[] threadIds = threadBean.getAllThreadIds();
    stream.println("Process Thread Dump: " + title);
    stream.println(threadIds.length + " active threads");
    for (long tid: threadIds) {
      ThreadInfo info = threadBean.getThreadInfo(tid, STACK_DEPTH);
      if (info == null) {
        stream.println("  Inactive");
        continue;
      }
      stream.println("Thread " +
                     getTaskName(info.getThreadId(),
                                 info.getThreadName()) + ":");
      Thread.State state = info.getThreadState();
      stream.println("  State: " + state);
      stream.println("  Blocked count: " + info.getBlockedCount());
      stream.println("  Waited count: " + info.getWaitedCount());
      if (contention) {
        stream.println("  Blocked time: " + info.getBlockedTime());
        stream.println("  Waited time: " + info.getWaitedTime());
      }
      if (state == Thread.State.WAITING) {
        stream.println("  Waiting on " + info.getLockName());
      } else  if (state == Thread.State.BLOCKED) {
        stream.println("  Blocked on " + info.getLockName());
        stream.println("  Blocked by " +
                       getTaskName(info.getLockOwnerId(),
                                   info.getLockOwnerName()));
      }
      stream.println("  Stack:");
      for (StackTraceElement frame: info.getStackTrace()) {
        stream.println("    " + frame.toString());
      }
    }
    stream.flush();
  }

  private static String getTaskName(long id, String name) {
    if (name == null) {
      return Long.toString(id);
    }
    return id + " (" + name + ")";
  }

  /**
   * Get and invoke the target method from the given object with given parameters
   * @param obj the object to get and invoke method from
   * @param methodName the name of the method to invoke
   * @param params the parameters for the method to invoke
   * @return the return value of the method invocation
   */
  @NonNull
  public static Object invokeMethod(Object obj, String methodName, Object... params) {
    Method m;
    try {
      m = obj.getClass().getMethod(methodName, getParameterTypes(params));
      m.setAccessible(true);
      return m.invoke(obj, params);
    } catch (NoSuchMethodException e) {
      throw new UnsupportedOperationException("Cannot find specified method " + methodName, e);
    } catch (IllegalAccessException e) {
      throw new UnsupportedOperationException("Unable to access specified method " + methodName, e);
    } catch (IllegalArgumentException e) {
      throw new UnsupportedOperationException("Illegal arguments supplied for method " + methodName,
          e);
    } catch (InvocationTargetException e) {
      throw new UnsupportedOperationException("Method threw an exception for " + methodName, e);
    }
  }

  private static Class<?>[] getParameterTypes(Object[] params) {
    Class<?>[] parameterTypes = new Class<?>[params.length];
    for (int i = 0; i < params.length; i++) {
      parameterTypes[i] = params[i].getClass();
    }
    return parameterTypes;
  }

}
