/*
 * Copyright (c) 2018, 2023, 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
 * @key headful
 * @bug 8146310
 * @summary [macosx] setDefaultMenuBar does not initialize screen menu bar
 * @author Alan Snyder
 * @library /test/lib
 * @run main/othervm TestNoScreenMenuBar
 * @requires (os.family == "mac")
 */

import java.awt.AWTException;
import java.awt.Desktop;
import java.awt.Frame;
import java.awt.Menu;
import java.awt.MenuBar;
import java.awt.Robot;
import java.awt.event.InputEvent;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;

import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.SwingUtilities;

import jdk.test.lib.process.ProcessTools;

public class TestNoScreenMenuBar
{
    static TestNoScreenMenuBar theTest;
    private Robot robot;
    private Process process;
    private boolean isActionPerformed;

    public TestNoScreenMenuBar()
    {
        try {
            robot = new Robot();
            robot.setAutoDelay(50);
        } catch (AWTException ex) {
            throw new RuntimeException(ex);
        }

        // activate another java application
        openOtherApplication();
        robot.delay(2000);

        // The failure mode is installing the default menu bar while the application is inactive
        Desktop desktop = Desktop.getDesktop();
        desktop.setDefaultMenuBar(createMenuBar());

        robot.delay(500);
        desktop.requestForeground(true);
        robot.delay(500);
    }

    JMenuBar createMenuBar()
    {
        JMenuBar mb = new JMenuBar();
        // A very long name makes it more likely that the robot will hit the menu
        JMenu menu = new JMenu("TestTestTestTestTestTestTestTestTestTest");
        mb.add(menu);
        JMenuItem item = new JMenuItem("TestTestTestTestTestTestTestTestTestTest");
        item.addActionListener(ev -> {
            isActionPerformed = true;
        });
        menu.add(item);
        return mb;
    }

    void dispose()
    {
        closeOtherApplication();
        Desktop.getDesktop().setDefaultMenuBar(null);
    }

    private void performMenuItemTest()
    {
        // Find the menu on the screen menu bar
        // The location depends upon the application name which is the name of the first menu.
        // Unfortunately, the application name can vary based on how the application is run.
        // The work around is to make the menu and the menu item names very long.

        int menuBarX = 250;
        int menuBarY = 11;
        int menuItemX = menuBarX;
        int menuItemY = 34;

        robot.mouseMove(menuBarX, menuBarY);
        robot.delay(100);
        robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
        robot.delay(100);
        robot.mouseMove(menuItemX, menuItemY);
        robot.delay(100);
        robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
        robot.waitForIdle();

        waitForAction();
    }

    private synchronized void waitForAction()
    {
        try {
            for (int i = 0; i < 10; i++) {
                if (isActionPerformed) {
                    return;
                }
                wait(100);
            }
        } catch (InterruptedException ex) {
        }
        throw new RuntimeException("Test failed: menu item action was not performed");
    }

    private void openOtherApplication() {
        process = execute();
    }

    private void closeOtherApplication() {
        if (process != null) {
            process.destroyForcibly();
        }
    }

    private Process execute() {
        try {
            ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder(
                    TestNoScreenMenuBar.class.getSimpleName(), "mark");
            return ProcessTools.startProcess("Other frame", pb);
        } catch (IOException ex) {
            throw new RuntimeException("Unable to execute command");
        }
    }

    private static void runSwing(Runnable r)
    {
        try {
            SwingUtilities.invokeAndWait(r);
        } catch (InterruptedException e) {
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        }
    }

    public static void main(String[] args)
    {
        if (!System.getProperty("os.name").contains("OS X")) {
            System.out.println("This test is for MacOS only. Automatically passed on other platforms.");
            return;
        }
        if (args.length != 0) {
            Frame frame = new Frame();
            MenuBar mb = new MenuBar();
            mb.add(new Menu("Hello"));
            frame.setMenuBar(mb);
            frame.setSize(300, 300);
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
            frame.toFront();
            return;
        }
        System.setProperty("apple.laf.useScreenMenuBar", "true");
        try {
            runSwing(() -> theTest = new TestNoScreenMenuBar());
            theTest.performMenuItemTest();
        } finally {
            if (theTest != null) {
                runSwing(() -> theTest.dispose());
            }
        }
    }
}
