package org.jdesktop.swinghelper.debug;

import static java.lang.Math.min;

import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;

final class DispatchInfo {

  // Provides the index to each hang event.
  private static final AtomicInteger hangCount = new AtomicInteger(0);

  // The last-dumped hung stack trace for this dispatch.
  private StackTraceElement[] lastReportedStack;

  // If so; what was the identifying hang number?
  private int hangNumber;

  // The EDT for this dispatch (for the purpose of getting stack traces).
  final Thread eventDispatchThread = Thread.currentThread();

  // The last time in milliseconds at which we saw a dispatch on the above thread.
  long lastDispatchTimeMillis = System.currentTimeMillis();

  private final Consumer<String> logConsumer;

  DispatchInfo(Consumer<String> logConsumer) {
    this.logConsumer = logConsumer;
  }

  void checkForHang() {
    if (timeSoFar() > EventDispatchThreadHangMonitor.UNREASONABLE_DISPATCH_DURATION_MS) {
      examineHang();
    }
  }

  private void examineHang() {
    StackTraceElement[] currentStack = eventDispatchThread.getStackTrace();
    if (isWaitingForNextEvent(currentStack)) {
      // Don't be fooled by a modal dialog if it's waiting for its next event.
      // As long as the modal dialog's event pump doesn't get stuck, it's okay for the outer pump to
      // be suspended.
      return;
    }

    if (stacksEqual(lastReportedStack, currentStack)) {
      // Skips reporting the same hang every time the timer goes off.
      return;
    }

    lastReportedStack = currentStack;
    hangNumber = hangCount.addAndGet(/* delta= */ 1);

    logConsumer.accept(
        "(hang #"
            + hangNumber
            + ") event dispatch thread stuck processing event for "
            + timeSoFar()
            + " ms:"
            + stackTraceToString(currentStack));
    checkForDeadlock();
  }

  private long timeSoFar() {
    return System.currentTimeMillis() - lastDispatchTimeMillis;
  }

  public void dispose() {
    if (lastReportedStack != null) {
      logConsumer.accept(
          "(hang #" + hangNumber + ") event dispatch thread unstuck after " + timeSoFar() + " ms.");
    }
  }

  // Checks whether the given stack looks like it's waiting for another event.
  // This relies on JDK implementation details.
  private static boolean isWaitingForNextEvent(StackTraceElement[] currentStack) {
    for (int i = 0; i < min(5, currentStack.length); i++) {
      if (stackTraceElementIs(currentStack[i], "java.awt.EventQueue", "getNextEvent", false)) {
        return true;
      }
    }
    return false;
  }

  // We can't use StackTraceElement.equals because that insists on checking the filename and line
  // number.
  // That would be version-specific.
  private static boolean stackTraceElementIs(
      StackTraceElement e, String className, String methodName, boolean isNative) {
    return e.getClassName().equals(className)
        && e.getMethodName().equals(methodName)
        && e.isNativeMethod() == isNative;
  }

  private String stackTraceToString(StackTraceElement[] stackTrace) {
    StringBuilder result = new StringBuilder();
    // We used to avoid showing any code above where this class gets
    // involved in event dispatch, but that hides potentially useful
    // information when dealing with modal dialogs. Maybe we should
    // reinstate that, but search from the other end of the stack?
    for (StackTraceElement stackTraceElement : stackTrace) {
      String indentation = "    ";
      result.append("\n").append(indentation).append(stackTraceElement);
    }
    return result.toString();
  }

  private boolean stacksEqual(StackTraceElement[] a, StackTraceElement[] b) {
    if (a == null) {
      return false;
    }
    if (a.length != b.length) {
      return false;
    }
    for (int i = 0; i < a.length; ++i) {
      if (!a[i].equals(b[i])) {
        return false;
      }
    }
    return true;
  }

  private void checkForDeadlock() {
    ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
    long[] threadIds = threadBean.findMonitorDeadlockedThreads();
    if (threadIds == null) {
      return;
    }
    logConsumer.accept("Deadlock detected involving the following threads:");
    for (ThreadInfo info : threadBean.getThreadInfo(threadIds, Integer.MAX_VALUE)) {
      logConsumer.accept(
          String.format(
              "Thread #%d %s (%s) waiting on lock(%s) held by %s stack:%s",
              info.getThreadId(),
              info.getThreadName(),
              info.getThreadState(),
              info.getLockName(),
              info.getLockOwnerName(),
              stackTraceToString(info.getStackTrace())));
    }
  }
}