/*
 * Copyright (c) 2010, 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.
 *
 * 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.
 */

/*
  @test
  @bug 6424157
  @author Artem Ananiev: area=eventqueue
  @run main PreserveDispatchThread
*/

import java.awt.*;
import java.awt.event.*;

public class PreserveDispatchThread {

    private static volatile Frame f;
    private static volatile Dialog d;

    private static volatile boolean isEDT = true;

    public static void main(String[] args) throws Exception {
        f = new Frame("F");
        f.setSize(320, 340);
        f.setLocationRelativeTo(null);
        f.setVisible(true);

        try {
            test1();
            if (!isEDT) {
                throw new RuntimeException("Test FAILED (test1): event dispatch thread is changed");
            }

            test2();
            if (!isEDT) {
                throw new RuntimeException("Test FAILED (test2): event dispatch thread is changed");
            }

            test3();
            if (!isEDT) {
                throw new RuntimeException("Test FAILED (test3): event dispatch thread is changed");
            }
        } finally {
            if (d != null) {
                d.dispose();
            }
            f.dispose();
        }
    }

    /*
     * Tests that push/pop doesn't change the dispatch thread if
     * called on EDT.
     */
    private static void test1() throws Exception {
        EventQueue.invokeAndWait(new Runnable() {
            @Override
            public void run() {
                TestEventQueue teq = new TestEventQueue();
                EventQueue seq = Toolkit.getDefaultToolkit().getSystemEventQueue();
                try {
                    seq.push(teq);
                    d = new TestDialog();
                    d.setVisible(true);
                    checkEDT();
                } finally {
                    teq.pop();
                }
                checkEDT();
            }
        });
    }

    /*
     * Tests that push/pop doesn't change the dispatch thread if
     * called on the main thread.
     */
    private static void test2() throws Exception {
        TestEventQueue teq = new TestEventQueue();
        EventQueue seq = Toolkit.getDefaultToolkit().getSystemEventQueue();
        try {
            seq.push(teq);
            EventQueue.invokeAndWait(new Runnable() {
                @Override
                public void run() {
                    checkEDT();
                    d = new TestDialog();
                    d.setVisible(true);
                    checkEDT();
                }
            });
        } finally {
            teq.pop();
        }
    }

    private static final Object test3Lock = new Object();
    private static boolean test3Sync = false;

    /*
     * A complex test: several nested invokeLater() are called and
     * in every runnable a check for EDT is performed. At the ent
     * of the test we wait for all the runnables to be processed
     * and the dialog is disposed; otherwise the last EDT check can
     * be later than this method returns and the whole test is passed.
     */
    private static void test3() throws Exception {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                d = new Dialog(f, true);
                d.setSize(240, 180);
                d.setLocationRelativeTo(f);
                EventQueue.invokeLater(new Runnable() {
                    @Override
                    public void run() {
                        d.setVisible(true);
                        checkEDT();
                    }
                });
                EventQueue.invokeLater(new Runnable() {
                    @Override
                    public void run() {
                        TestEventQueue teq = new TestEventQueue();
                        EventQueue seq = Toolkit.getDefaultToolkit().getSystemEventQueue();
                        try {
                            seq.push(teq);
                            checkEDT();
                            EventQueue.invokeLater(new Runnable() {
                                @Override
                                public void run() {
                                    d.dispose();
                                    checkEDT();
                                    synchronized (test3Lock) {
                                        test3Sync = true;
                                        test3Lock.notify();
                                    }
                                }
                            });
                        } finally {
                            teq.pop();
                        }
                        checkEDT();
                    }
                });
                checkEDT();
            }
        });
        synchronized (test3Lock) {
            while (!test3Sync) {
                try {
                    test3Lock.wait();
                } catch (InterruptedException ie) {
                    break;
                }
            }
        }
        // Make sure all the nested invokeLater/invokeAndWait are processed
        EventQueue.invokeAndWait(new Runnable() {
            @Override
            public void run() {
            }
        });
    }

    private static void checkEDT() {
        isEDT = isEDT && EventQueue.isDispatchThread();
    }

    private static class TestEventQueue extends EventQueue {
        public TestEventQueue() {
            super();
        }
        public void pop() {
            super.pop();
        }
    }

    private static class TestDialog extends Dialog {
        private volatile boolean dialogShown = false;
        private volatile boolean paintCalled = false;
        public TestDialog() {
            super(f, true);
            setSize(240, 180);
            setLocationRelativeTo(f);
            addComponentListener(new ComponentAdapter() {
                @Override
                public void componentShown(ComponentEvent e) {
                    if (paintCalled) {
                        dispose();
                    }
                    dialogShown = true;
                }
            });
        }
        @Override
        public void paint(Graphics g) {
            if (dialogShown) {
                dispose();
            }
            paintCalled = true;
        }
    }

}
