/*
 * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package sun.awt;

import java.awt.AWTEvent;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.Map;
import java.util.Set;

import sun.awt.util.ThreadGroupUtils;
import sun.util.logging.PlatformLogger;

/**
 * This class is to let AWT shutdown automatically when a user is done
 * with AWT. It tracks AWT state using the following parameters:
 * <ul>
 * <li>{@code peerMap} - the map between the existing peer objects
 *     and their associated targets
 * <li>{@code toolkitThreadBusy} - whether the toolkit thread
 *     is waiting for a new native event to appear in its queue
 *     or is dispatching an event
 * <li>{@code busyThreadSet} - a set of all the event dispatch
 *     threads that are busy at this moment, i.e. those that are not
 *     waiting for a new event to appear in their event queue.
 * </ul><p>
 * AWT is considered to be in ready-to-shutdown state when
 * {@code peerMap} is empty and {@code toolkitThreadBusy}
 * is false and {@code busyThreadSet} is empty.
 * The internal AWTAutoShutdown logic secures that the single non-daemon
 * thread ({@code blockerThread}) is running when AWT is not in
 * ready-to-shutdown state. This blocker thread is to prevent AWT from
 * exiting since the toolkit thread is now daemon and all the event
 * dispatch threads are started only when needed. Once it is detected
 * that AWT is in ready-to-shutdown state this blocker thread waits
 * for a certain timeout and if AWT state doesn't change during timeout
 * this blocker thread terminates all the event dispatch threads and
 * exits.
 */
public final class AWTAutoShutdown implements Runnable {

    private static final AWTAutoShutdown theInstance = new AWTAutoShutdown();

    /**
     * This lock object is used to synchronize shutdown operations.
     */
    private final Object mainLock = new Object();

    /**
     * This lock object is to secure that when a new blocker thread is
     * started it will be the first who acquire the main lock after
     * the thread that created the new blocker released the main lock
     * by calling lock.wait() to wait for the blocker to start.
     */
    private final Object activationLock = new Object();

    /**
     * This set keeps references to all the event dispatch threads that
     * are busy at this moment, i.e. those that are not waiting for a
     * new event to appear in their event queue.
     * Access is synchronized on the main lock object.
     */
    private final Set<Thread> busyThreadSet = new HashSet<>(7);

    /**
     * Indicates whether the toolkit thread is waiting for a new native
     * event to appear or is dispatching an event.
     */
    private boolean toolkitThreadBusy = false;

    /**
     * This is a map between components and their peers.
     * we should work with in under activationLock&mainLock lock.
     */
    private final Map<Object, Object> peerMap = new IdentityHashMap<>();

    /**
     * References the alive non-daemon thread that is currently used
     * for keeping AWT from exiting.
     */
    private Thread blockerThread = null;

    /**
     * We need this flag to secure that AWT state hasn't changed while
     * we were waiting for the safety timeout to pass.
     */
    private boolean timeoutPassed = false;

    /**
     * Once we detect that AWT is ready to shutdown we wait for a certain
     * timeout to pass before stopping event dispatch threads.
     */
    private static final int SAFETY_TIMEOUT = 1000;

    /**
     * Constructor method is intentionally made private to secure
     * a single instance. Use getInstance() to reference it.
     *
     * @see     AWTAutoShutdown#getInstance
     */
    private AWTAutoShutdown() {}

    /**
     * Returns reference to a single AWTAutoShutdown instance.
     */
    public static AWTAutoShutdown getInstance() {
        return theInstance;
    }

    /**
     * Notify that the toolkit thread is not waiting for a native event
     * to appear in its queue.
     *
     * @see     AWTAutoShutdown#notifyToolkitThreadFree
     * @see     AWTAutoShutdown#setToolkitBusy
     * @see     AWTAutoShutdown#isReadyToShutdown
     */
    public static void notifyToolkitThreadBusy() {
        getInstance().setToolkitBusy(true);
    }

    /**
     * Notify that the toolkit thread is waiting for a native event
     * to appear in its queue.
     *
     * @see     AWTAutoShutdown#notifyToolkitThreadFree
     * @see     AWTAutoShutdown#setToolkitBusy
     * @see     AWTAutoShutdown#isReadyToShutdown
     */
    public static void notifyToolkitThreadFree() {
        getInstance().setToolkitBusy(false);
    }

    /**
     * Add a specified thread to the set of busy event dispatch threads.
     * If this set already contains the specified thread or the thread is null,
     * the call leaves this set unchanged and returns silently.
     *
     * @param thread thread to be added to this set, if not present.
     * @see     AWTAutoShutdown#notifyThreadFree
     * @see     AWTAutoShutdown#isReadyToShutdown
     */
    public void notifyThreadBusy(final Thread thread) {
        if (thread == null) {
            return;
        }
        synchronized (activationLock) {
            synchronized (mainLock) {
                if (blockerThread == null) {
                    activateBlockerThread();
                } else if (isReadyToShutdown()) {
                    mainLock.notifyAll();
                    timeoutPassed = false;
                }
                busyThreadSet.add(thread);
            }
        }
    }

    /**
     * Remove a specified thread from the set of busy event dispatch threads.
     * If this set doesn't contain the specified thread or the thread is null,
     * the call leaves this set unchanged and returns silently.
     *
     * @param thread thread to be removed from this set, if present.
     * @see     AWTAutoShutdown#notifyThreadBusy
     * @see     AWTAutoShutdown#isReadyToShutdown
     */
    public void notifyThreadFree(final Thread thread) {
        if (thread == null) {
            return;
        }
        synchronized (activationLock) {
            synchronized (mainLock) {
                busyThreadSet.remove(thread);
                if (isReadyToShutdown()) {
                    mainLock.notifyAll();
                    timeoutPassed = false;
                }
            }
        }
    }

    /**
     * Notify that the peermap has been updated, that means a new peer
     * has been created or some existing peer has been disposed.
     *
     * @see     AWTAutoShutdown#isReadyToShutdown
     */
    void notifyPeerMapUpdated() {
        synchronized (activationLock) {
            synchronized (mainLock) {
                if (!isReadyToShutdown() && blockerThread == null) {
                    activateBlockerThread();
                } else {
                    mainLock.notifyAll();
                    timeoutPassed = false;
                }
            }
        }
    }

    /**
     * Determine whether AWT is currently in ready-to-shutdown state.
     * AWT is considered to be in ready-to-shutdown state if
     * {@code peerMap} is empty and {@code toolkitThreadBusy}
     * is false and {@code busyThreadSet} is empty.
     *
     * @return true if AWT is in ready-to-shutdown state.
     */
    private boolean isReadyToShutdown() {
        return (!toolkitThreadBusy &&
                 peerMap.isEmpty() &&
                 busyThreadSet.isEmpty());
    }

    /**
     * Notify about the toolkit thread state change.
     *
     * @param busy true if the toolkit thread state changes from idle
     *             to busy.
     * @see     AWTAutoShutdown#notifyToolkitThreadBusy
     * @see     AWTAutoShutdown#notifyToolkitThreadFree
     * @see     AWTAutoShutdown#isReadyToShutdown
     */
    private void setToolkitBusy(final boolean busy) {
        if (busy != toolkitThreadBusy) {
            synchronized (activationLock) {
                synchronized (mainLock) {
                    if (busy != toolkitThreadBusy) {
                        if (busy) {
                            if (blockerThread == null) {
                                activateBlockerThread();
                            } else if (isReadyToShutdown()) {
                                mainLock.notifyAll();
                                timeoutPassed = false;
                            }
                            toolkitThreadBusy = busy;
                        } else {
                            toolkitThreadBusy = busy;
                            if (isReadyToShutdown()) {
                                mainLock.notifyAll();
                                timeoutPassed = false;
                            }
                        }
                    }
                }
            }
        }
    }

    /**
     * Implementation of the Runnable interface.
     * Encapsulates the blocker thread functionality.
     *
     * @see     AWTAutoShutdown#isReadyToShutdown
     */
    public void run() {
        Thread currentThread = Thread.currentThread();
        boolean interrupted = false;
        synchronized (mainLock) {
            try {
                /* Notify that the thread is started. */
                mainLock.notifyAll();
                while (blockerThread == currentThread) {
                    mainLock.wait();
                    timeoutPassed = false;
                    /*
                     * This loop is introduced to handle the following case:
                     * it is possible that while we are waiting for the
                     * safety timeout to pass AWT state can change to
                     * not-ready-to-shutdown and back to ready-to-shutdown.
                     * In this case we have to wait once again.
                     * NOTE: we shouldn't break into the outer loop
                     * in this case, since we may never be notified
                     * in an outer infinite wait at this point.
                     */
                    while (isReadyToShutdown()) {
                        if (timeoutPassed) {
                            timeoutPassed = false;
                            blockerThread = null;
                            break;
                        }
                        timeoutPassed = true;
                        mainLock.wait(SAFETY_TIMEOUT);
                    }
                }
            } catch (InterruptedException e) {
                interrupted = true;
            } finally {
                if (blockerThread == currentThread) {
                    blockerThread = null;
                }
            }
        }
        if (!interrupted) {
            AppContext.stopEventDispatchThreads();
        }
    }

    static AWTEvent getShutdownEvent() {
        return new AWTEvent(getInstance(), 0) {
        };
    }

    /**
     * Creates and starts a new blocker thread. Doesn't return until
     * the new blocker thread starts.
     */
    private void activateBlockerThread() {
        String name = "AWT-Shutdown";
        Thread thread = new Thread(ThreadGroupUtils.getRootThreadGroup(), this, name, 0, false);
        thread.setContextClassLoader(null);
        thread.setDaemon(false);
        blockerThread = thread;
        thread.start();
        try {
            /* Wait for the blocker thread to start. */
            mainLock.wait();
        } catch (InterruptedException e) {
            System.err.println("AWT blocker activation interrupted:");
            e.printStackTrace();
        }
    }

    void registerPeer(final Object target, final Object peer) {
        synchronized (activationLock) {
            synchronized (mainLock) {
                peerMap.put(target, peer);
                notifyPeerMapUpdated();
            }
        }
    }

    void unregisterPeer(final Object target, final Object peer) {
        synchronized (activationLock) {
            synchronized (mainLock) {
                if (peerMap.get(target) == peer) {
                    peerMap.remove(target);
                    notifyPeerMapUpdated();
                }
            }
        }
    }

    Object getPeer(final Object target) {
        synchronized (activationLock) {
            synchronized (mainLock) {
                return peerMap.get(target);
            }
        }
    }

    void dumpPeers(final PlatformLogger aLog) {
        if (aLog.isLoggable(PlatformLogger.Level.FINE)) {
            synchronized (activationLock) {
                synchronized (mainLock) {
                    aLog.fine("Mapped peers:");
                    for (Object key : peerMap.keySet()) {
                        aLog.fine(key + "->" + peerMap.get(key));
                    }
                }
            }
        }
    }

} // class AWTAutoShutdown
