package org.jdesktop.swinghelper.debug;

import static java.util.concurrent.TimeUnit.MILLISECONDS;

import java.awt.AWTEvent;
import java.awt.EventQueue;
import java.awt.Toolkit;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.function.Consumer;

/**
 * Monitors the AWT event dispatch thread for events that take longer than a certain time to be
 * dispatched.
 * <p/>
 * The principle is to record the time at which we start processing an event, and have another
 * thread check frequently to see if we're still processing. If the other thread notices that we've
 * been processing a single event for too long, it prints a stack trace showing what the event
 * dispatch thread is doing, and continues to time it until it finally finishes.
 * <p/>
 * This is useful in determining what code is causing your Java application's GUI to be
 * unresponsive.
 *
 * <p>The original source code can be found here<br>
 * <a href="https://github.com/floscher/swinghelper/blob/master/src/java/org/jdesktop/swinghelper/debug/EventDispatchThreadHangMonitor.java">
 * EventDispatchThreadHangMonitor.java</a>
 * </p>
 */
public final class EventDispatchThreadHangMonitor extends EventQueue implements Runnable {

  // Time to wait between checks that the event dispatch thread isn't hung.
  private static final long CHECK_INTERVAL_MS = 100;

  // Maximum time we won't warn about. This used to be 500 ms, but 1.5 on
  // late-2004 hardware isn't really up to it; there are too many parts of
  // the JDK that can go away for that long (often code that has to be
  // called on the event dispatch thread, like font loading).
  static final long UNREASONABLE_DISPATCH_DURATION_MS = 1000;

  // The currently outstanding event dispatches. The implementation of
  // modal dialogs is a common cause for multiple outstanding dispatches.
  private final Deque<DispatchInfo> dispatches = new ArrayDeque<>();

  // The scheduler to regularly check whether a hang event is detected or not.
  private final ScheduledExecutorService scheduler =
      Executors.newSingleThreadScheduledExecutor(
          runnable -> {
            Thread t = new Thread(runnable);
            t.setDaemon(true);
            return t;
          });

  private final Consumer<String> logConsumer;

  /**
   * Constructs {@link EventDispatchThreadHangMonitor}.
   */
  public EventDispatchThreadHangMonitor() {
    this(System.out::println);
  }

  /**
   * Constructs {@link EventDispatchThreadHangMonitor}.
   *
   * @param logConsumer the custom log consumer
   */
  public EventDispatchThreadHangMonitor(Consumer<String> logConsumer) {
    this.logConsumer = logConsumer;
  }

  /**
   * Sets up hang detection for the event dispatch thread.
   */
  public void initMonitoring() {
    Toolkit.getDefaultToolkit().getSystemEventQueue().push(this);
    Future<?> unused = scheduler.scheduleWithFixedDelay(this, 0, CHECK_INTERVAL_MS, MILLISECONDS);
  }

  @Override
  protected void dispatchEvent(AWTEvent event) {
    DispatchInfo currentDispatchInfo = new DispatchInfo(logConsumer);
    try {
      synchronized (dispatches) {
        dispatches.addLast(currentDispatchInfo);
      }
      super.dispatchEvent(event);
    } finally {
      synchronized (dispatches) {
        // We've finished the most nested dispatch, and don't need it any longer.
        dispatches.removeLast();
        currentDispatchInfo.dispose();

        // The other dispatches, which have been waiting, need to be credited extra time.
        // We do this rather simplistically by pretending they've just been redispatched.
        Thread currentEventDispatchThread = Thread.currentThread();
        for (DispatchInfo dispatchInfo : dispatches) {
          if (dispatchInfo.eventDispatchThread == currentEventDispatchThread) {
            dispatchInfo.lastDispatchTimeMillis = System.currentTimeMillis();
          }
        }
      }
    }
  }

  @Override
  public void run() {
    synchronized (dispatches) {
      if (!dispatches.isEmpty()) {
        // Only the most recent dispatch can be hung; nested dispatches
        // by their nature cause the outer dispatch pump to be suspended.
        dispatches.getLast().checkForHang();
      }
    }
  }
}