/*
* Copyright (c) 2013, 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 sun.awt.OSInfo;

import java.awt.*;
import java.awt.Robot;
import java.awt.event.InputEvent;
import java.lang.InterruptedException;
import java.lang.System;
import java.lang.Thread;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import javax.swing.*;

/*
 * @test
 * @bug 8024185
 * @summary Native Mac OS X full screen does not work after showing the splash
 * @library ../
 * @build GenerateTestImage
 * @run main GenerateTestImage
 * @author Petr Pchelko area=awt.event
 * @run main/othervm -splash:test.png FullScreenAfterSplash
 */
public class FullScreenAfterSplash {

    private static JFrame frame;

    private static volatile boolean windowEnteringFullScreen = false;
    private static volatile boolean windowEnteredFullScreen = false;

    public static void main(String[] args) throws Exception {

        if (OSInfo.getOSType() != OSInfo.OSType.MACOSX) {
            System.out.println("The test is applicable only to Mac OS X. Passed");
            return;
        }
        try {
            //Move the mouse out, because it could interfere with the test.
            Robot r = new Robot();
            r.mouseMove(0, 0);
            sleep();

            SwingUtilities.invokeAndWait(FullScreenAfterSplash::createAndShowGUI);
            sleep();

            Point fullScreenButtonPos = frame.getLocation();
            fullScreenButtonPos.translate(frame.getWidth() - 10, 10);
            r.mouseMove(fullScreenButtonPos.x, fullScreenButtonPos.y);

            //Cant use waitForIdle for full screen transition.
            int waitCount = 0;
            while (!windowEnteringFullScreen) {
                r.mousePress(InputEvent.BUTTON1_MASK);
                r.mouseRelease(InputEvent.BUTTON1_MASK);
                Thread.sleep(100);
                if (waitCount++ > 10) {
                    System.err.println("Can't enter full screen mode. Failed.");
                    System.exit(1);
                }
            }

            waitCount = 0;
            while (!windowEnteredFullScreen) {
                Thread.sleep(100);
                if (waitCount++ > 10) {
                    System.err.println("Can't enter full screen mode. Failed.");
                    System.exit(1);
                }
            }
        } finally {
            if (frame != null) {
                frame.dispose();
            }
        }
    }

    private static void createAndShowGUI() {
        frame = new JFrame(" Fullscreen OSX Bug ");
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        enableFullScreen(frame);
        frame.setBounds(100, 100, 100, 100);
        frame.pack();
        frame.setVisible(true);
    }

    /*
     *  Use reflection to make a test compilable on not Mac OS X
     */
    private static void enableFullScreen(Window window) {
        try {
            Class<?> fullScreenUtilities = Class.forName("com.apple.eawt.FullScreenUtilities");
            Method setWindowCanFullScreen = fullScreenUtilities.getMethod("setWindowCanFullScreen", Window.class, boolean.class);
            setWindowCanFullScreen.invoke(fullScreenUtilities, window, true);
            Class fullScreenListener = Class.forName("com.apple.eawt.FullScreenListener");
            Object listenerObject = Proxy.newProxyInstance(fullScreenListener.getClassLoader(), new Class[]{fullScreenListener}, (proxy, method, args) -> {
                switch (method.getName()) {
                    case "windowEnteringFullScreen":
                        windowEnteringFullScreen = true;
                        break;
                    case "windowEnteredFullScreen":
                        windowEnteredFullScreen = true;
                        break;
                }
                return null;
            });
            Method addFullScreenListener = fullScreenUtilities.getMethod("addFullScreenListenerTo", Window.class, fullScreenListener);
            addFullScreenListener.invoke(fullScreenUtilities, window, listenerObject);
        } catch (Exception e) {
            throw new RuntimeException("FullScreen utilities not available", e);
        }
    }

    private static void sleep() {
        try {
            Thread.sleep(500);
        } catch (InterruptedException ignored) { }
    }
}
