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

import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Label;
import java.awt.Menu;
import java.awt.MenuBar;
import java.awt.MenuItem;
import java.awt.Panel;
import java.awt.Rectangle;
import java.awt.TextArea;
import java.awt.Window;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.lang.reflect.InvocationTargetException;
import javax.swing.SwingUtilities;

/*
 * @test
 * @bug 4124096 4183412 6234295
 * @key headful
 * @library /java/awt/regtesthelpers
 * @build PassFailJFrame
 * @summary Test dialog's modality with a series of Window, Frame and Dialog
 * For bug 4183412, verify that the Menu on any Frame cannot be popped up
 * when there is a modal dialog up.
 * @run main/manual ModalDialogTest
 */

class TestPanel extends Panel {
    private static MouseListener mouseListener;
    private static MouseMotionListener mouseMotionListener;
    private static FocusListener focusListener;
    static TextArea ta;

    public TestPanel() {
        if (mouseListener == null) {
            mouseListener = new MouseListener() {
                public void mouseEntered(MouseEvent e) {
                    ta.append(e.getComponent().getName()+":mouseEntered\n");
                }
                public void mouseExited(MouseEvent e) {
                    ta.append(e.getComponent().getName()+":mouseExited\n");
                }
                public void mousePressed(MouseEvent e) {
                    ta.append(e.getComponent().getName()+":mousePressed\n");
                }

                public void mouseReleased(MouseEvent e) {
                    ta.append(e.getComponent().getName()+":mouseReleased\n");
                }
                public void mouseClicked(MouseEvent e) {
                    ta.append(e.getComponent().getName()+":mouseClicked\n");
                }
            };
        }

        if (mouseMotionListener == null) {
            mouseMotionListener = new MouseMotionListener() {
                public void mouseMoved(MouseEvent e) {
                    ta.append(e.getComponent().getName()+":mouseMoved\n");
                }
                public void mouseDragged(MouseEvent e) {
                    ta.append(e.getComponent().getName()+":mouseDragged\n");
                }
            };
        }

        if (focusListener == null) {
           focusListener = new FocusListener() {
              public void focusGained(FocusEvent e) {
                  ta.append(e.getComponent().getName()+":focusGained\n");
              }
              public void focusLost(FocusEvent e) {
                  ta.append(e.getComponent().getName()+":focusLost\n");
              }
          };
       }

        Button b = new Button("Heavy Button");
        b.setName("HeavyButton");
        b.addMouseListener(mouseListener);
        b.addMouseMotionListener(mouseMotionListener);
        b.addFocusListener(focusListener);
        add(b);

        Component c = new Container() {
            public Dimension getPreferredSize() {
                return new Dimension(50,50);
            }
            public void paint(Graphics g) {
                Dimension d = getSize();
                g.setColor(Color.blue);
                g.fillRect(0, 0, d.width, d.height);
            }
        };
        c.setName("Lightweight");
        c.setBackground(Color.blue);
        c.addMouseListener(mouseListener);
        c.addMouseMotionListener(mouseMotionListener);
        c.addFocusListener(focusListener);
        add(c);
    }

    public TestPanel(TextArea t) {
        this();
        ta = t;
        add(ta);
    }
}

class WindowPanel extends Panel {
    static int windows = 0;
    static int dialogs = 0;
    static int frames = 1;
    static int modalDialogs = 0;

    private static WindowListener winListener;
    private static FocusListener focusListener;

    private final Button windowButton;
    private final Button dialogButton;
    private final Button frameButton;
    private final Button modalDialogButton;

    public static void buildAndShowWindow(Window win, Component top,
                                          TestPanel center, Component bottom) {
        final TextArea ta = TestPanel.ta;

        if (winListener == null) {
            winListener = new WindowListener() {
                public void windowOpened(WindowEvent e) {
                    ta.append(e.getWindow().getName()+":windowOpened\n");
                }
                public void windowClosing(WindowEvent e) {
                    ta.append(e.getWindow().getName()+":windowClosing\n");
                    e.getWindow().setVisible(false);
                }
                public void windowClosed(WindowEvent e) {
                    ta.append(e.getWindow().getName()+":windowClosed\n");
                }
                public void windowIconified(WindowEvent e) {
                    ta.append(e.getWindow().getName()+":windowIconified\n");
                }
                public void windowDeiconified(WindowEvent e) {
                    ta.append(e.getWindow().getName()+":windowDeiconified\n");
                }
                public void windowActivated(WindowEvent e) {
                    ta.append(e.getWindow().getName()+":windowActivated\n");
                }
                public void windowDeactivated(WindowEvent e) {
                    ta.append(e.getWindow().getName()+":windowDeactivated\n");
                }
            };
         }

        if (focusListener == null) {
            focusListener = new FocusListener() {
                public void focusGained(FocusEvent e) {
                    ta.append(e.getComponent().getName()+":focusGained\n");
                }
                public void focusLost(FocusEvent e) {
                    ta.append(e.getComponent().getName()+":focusLost\n");
                }
            };
        }

        win.addWindowListener(winListener);
        win.addFocusListener(focusListener);

        if (!(win instanceof Frame)) {
            Rectangle pBounds = win.getOwner().getBounds();
            win.setLocation(pBounds.x, pBounds.y + pBounds.height);
        }

        win.add(top, BorderLayout.NORTH);
        win.add(center, BorderLayout.CENTER);
        win.add(bottom, BorderLayout.SOUTH);
        win.pack();
        if (windows != 0 || frames != 1 || dialogs != 0 || modalDialogs != 0) {
            win.setVisible(true);
        }

        PassFailJFrame.addTestWindow(win);
    }

    public Window getParentWindow() {
        Container p = getParent();
        while (p != null && !(p instanceof Window)) {
            p = p.getParent();
        }
        return (Window)p;
    }

    public WindowPanel() {

        windowButton = new Button("New Window...");
        windowButton.addActionListener(e -> {
            Window owner = getParentWindow();
            Window window = new Window(owner);
            window.setName("Window "+ windows++);

            Panel p = new Panel();
            p.setLayout(new GridLayout(0, 1));
            p.add(new Label("Title: "+ window.getName()));
            p.add(new Label("Owner: "+ owner.getName()));

            buildAndShowWindow(window, p, new TestPanel(), new WindowPanel());
        });
        add(windowButton);

        frameButton = new Button("New Frame...");
        frameButton.addActionListener(e -> {
            Frame frame = new Frame("Frame "+ frames++);
            frame.setName(frame.getTitle());
            MenuBar mb=new MenuBar();
            Menu m=new Menu("Menu");
            m.add(new MenuItem("Dummy menu item"));
            frame.setMenuBar(mb);
            mb.add(m);

            buildAndShowWindow(frame, new Label("Owner: none"),
                               new TestPanel(), new WindowPanel());
        });
        add(frameButton);

        dialogButton = new Button("New Dialog...");
        dialogButton.addActionListener(e -> {
            Window owner = getParentWindow();
            Dialog dialog;
            if (owner instanceof Dialog) {
                dialog = new Dialog((Dialog)owner, "Dialog "+ dialogs++, false);
            } else {
                dialog = new Dialog((Frame)owner, "Dialog "+ dialogs++, false);
            }
            dialog.setName(dialog.getTitle());

            buildAndShowWindow(dialog, new Label("Owner: "+ owner.getName()),
                               new TestPanel(), new WindowPanel());
        });
        add(dialogButton);

        modalDialogButton = new Button("New Modal Dialog...");
        modalDialogButton.addActionListener(e -> {
            Window owner = getParentWindow();
            Dialog dialog;
            if (owner instanceof Dialog) {
                dialog = new Dialog((Dialog)owner, "ModalDialog "+ modalDialogs++,
                                    true);
            } else {
                dialog = new Dialog((Frame)owner, "ModalDialog "+ modalDialogs++,
                                    true);
            }
            dialog.setName(dialog.getTitle());
            buildAndShowWindow(dialog, new Label("Owner: "+ owner.getName()),
                               new TestPanel(), new WindowPanel());
        });
        add(modalDialogButton);
    }

    public void addNotify() {
        super.addNotify();
        Window owner = getParentWindow();
        if (!(owner instanceof Frame) && !(owner instanceof Dialog)) {
            dialogButton.setEnabled(false);
            modalDialogButton.setEnabled(false);
        }
    }
}

public class ModalDialogTest {
    private static Frame frame= new Frame("RootFrame");
    private static final boolean isMacOS = System.getProperty("os.name")
                                          .contains("OS X");

    private static String getInstructions() {
        StringBuilder sb = new StringBuilder();

        sb.append("""
            When the test is ready, one Root Frame is shown. The Frame has a
            "Heavy button", a blue lightweight component and a TextArea to
            display message. The Root Frame has no owner.

            \t *. Click button "New Frame" to show a new Frame, notice that this
            \t Frame 1 has a Menu added. Verify that Menu is accessible.

            \t *. Now click button "New Modal Dialog" to bring up a modal dialog.
            """);

        if (!isMacOS) { //We do not test screen menu bar on macOS
            sb.append("""
                  \t Verify that the Menu in Frame 1 is not accessible anymore.
                  \t That tests the fix for 4183412 on Solaris and
                  \t 6234295 on XToolkit.\n
                  """);
        }

        sb.append("""
            \t *. You can click different buttons several times, but verify that
            \t whenever a Modal dialog is up, no mouse event can be generated for
            \t other windows.
            \t (All the events are printed in the TextArea in Root Window).
            \t This tests the fix for 4124096.

            Close the modal dialog before pressing fail/pass button.
            """);

        return sb.toString();
    }

    public static void main(String[] args) throws InterruptedException,
                                                  InvocationTargetException {
        PassFailJFrame passFailJFrame = new PassFailJFrame("ModalDialogTest " +
        "Instructions", getInstructions(), 10, 20, 60);

        SwingUtilities.invokeAndWait(() ->{
            WindowPanel.buildAndShowWindow(
                frame,
                new Label("Owner: none"),
                new TestPanel(new TextArea(10, 30)),
                new WindowPanel()
            );

            // adding only the root frame to be positioned
            // w.r.t instruction frame
            passFailJFrame.positionTestWindow(frame, PassFailJFrame.Position.HORIZONTAL);
            frame.setVisible(true);
        });

        passFailJFrame.awaitAndCheck();
    }
}
