/*
 * Copyright (c) 2004, 2007, 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 5085626
 @summary Exponential performance regression in AWT components (multiple mon)
 @run main WPanelPeerPerf
*/

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

/**
 * This test must be run on a multi-screen system.
 * This test works by moving a Frame back and forth between the screens a few
 * times.  When the bug is active, the first move will overwhelm the EDT with
 * recursive display change calls.  The test fails if it takes too long to
 * service the setLocation() calls and send componentMoved() events.
 */
public class WPanelPeerPerf {

    private static final int NESTED_PANELS = 25;
    private static final int ITERATIONS_PER_SCREEN = 3;
    private static final int MAX_WAIT_PER_SCREEN = 2500;
    private static final int PAUSE_BETWEEN_MOVES = 500;


    private static Object showLock = new Object();

    private static Counter instance = null;
    public static Counter getCounter() {
        if (instance == null) {
            instance = new Counter();
        }
        return instance;
    }

    private static class Counter {
        int counter;
        Counter() { counter = 0; }
    }

    // This one is very slow!
    public static void testAWT() {
        // fail if only on one screen
        int numScreens = GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices().length;
        if (numScreens < 2) {
            System.err.println("Test must be run on a multiscreen system");
            return;
        }
        final Frame frame = new Frame("AWT WPanelPeerPerf");
        frame.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent ev) {
                System.exit(0);
            }
            public void windowOpened(WindowEvent e) {
                synchronized(showLock) {
                    showLock.notify();
                }
            }
        });
        frame.setLayout(new BorderLayout());
        Label label = new Label("Hello world");
        frame.add(label, BorderLayout.NORTH);
        Panel panel = new Panel(new BorderLayout());
        Panel currentPanel = panel;
        for (int i = 0; i < NESTED_PANELS; i++) {
            Panel newPanel = new Panel(new BorderLayout());
            currentPanel.add(newPanel, BorderLayout.CENTER);
            currentPanel = newPanel;
        }
        currentPanel.add(new Label("WPanelPeerPerf"));
        frame.add(panel, BorderLayout.CENTER);
        Button btn = new Button("OK");
        frame.add(btn, BorderLayout.SOUTH);
        frame.pack();

        frame.addComponentListener(new ComponentAdapter() {
            public void componentMoved(ComponentEvent e) {
                System.out.println("Frame moved: ");
                Counter ctr = getCounter();
                synchronized(ctr) {
                    ctr.counter++;
                    ctr.notify();
                }
            }
        });
        synchronized(showLock) {
            try {
                frame.setVisible(true);
                showLock.wait();
            }
            catch (InterruptedException e) {
                e.printStackTrace();
                throw new RuntimeException("Problem with showLock");
            }
        }
        runTest(frame);
    }

    public static void runTest(Frame theFrame) {
        System.out.println("Running test");
        GraphicsDevice[] devs = GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices();
        Point[] points = new Point[devs.length];

        for (int i = 0; i < points.length; i++) {
            Rectangle bounds = devs[i].getDefaultConfiguration().getBounds();
            points[i] = new Point(bounds.x + (bounds.width / 2),
                    bounds.y + (bounds.height / 2));
            System.out.println("Added point:" + points[i]);
        }

        final Frame localFrame = theFrame;

        for (int n = 0; n < ITERATIONS_PER_SCREEN; n++) {
            for (int i = 0; i < points.length; i++) {
                final Point contextPoint = points[i];
                SwingUtilities.invokeLater(new Runnable() {
                    public void run() {
                        localFrame.setLocation(contextPoint);
                    }
                });
                try {
                    Thread.sleep(PAUSE_BETWEEN_MOVES);
                }
                catch (InterruptedException e) {
                    System.out.println("Interrupted during iteration");
                }
            }
        }
        Counter ctr = getCounter();
        synchronized(ctr) {
            try {
                if (ctr.counter < ITERATIONS_PER_SCREEN * devs.length) {
                    // If test hasn't finished, wait for maximum time
                    // If we get interrupted, test fails
                    ctr.wait((long)(ITERATIONS_PER_SCREEN * MAX_WAIT_PER_SCREEN * devs.length));
                    System.out.println("after wait");
                    if (ctr.counter < ITERATIONS_PER_SCREEN * devs.length) {
                        throw new RuntimeException("Waited too long for all the componentMoved()s");
                    }
                }
            }
            catch(InterruptedException e) {
                e.printStackTrace();
                throw new RuntimeException("Wait interrupted - ???");
            }
            System.out.println("Counter reads: " + ctr.counter);
        }

    }
    public static void main(String[] args) {
        testAWT();
    }
}
