/*
 * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved.
 * Copyright (c) 2022, JetBrains s.r.o.. 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 8294426
 * @summary The test verifies that a press {@link java.awt.event.MouseEvent}
 * contains correct modifiers although the according native mouse event is
 * accompanied by no mouse modifiers.
 * @author Nikita.Provotorov@jetbrains.com
 *
 * @key headful
 * @requires (os.family == "mac")
 *
 * @modules java.desktop/java.awt:open java.desktop/sun.lwawt:open java.desktop/sun.lwawt.macosx:+open
 * @run main/othervm MouseMacTouchPressEventModifiers
 */

import sun.lwawt.macosx.CocoaConstants;
import sun.lwawt.macosx.LWCToolkit;

import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;


/**
 * Sometimes native mouse events aren't accompanied by the correct mouse modifiers, i.e.
 *  {@link sun.lwawt.macosx.NSEvent#nsToJavaModifiers} returns 0 inside
 *  {@link sun.lwawt.macosx.CPlatformResponder#handleMouseEvent(int, int, int, int, int, int, int, int)}.
 * E.g. the situation above happens when a user taps (NOT clicks) on a trackpad on a M2 MacBooks while
 *  System Preferences -> Trackpad -> Tap to click is turned on.
 * The test emulates the situation via a direct invocation of
 *  {@link sun.lwawt.macosx.CPlatformResponder#handleMouseEvent(int, int, int, int, int, int, int, int)};
 *  unfortunately it's impossible to use {@link java.awt.Robot} because its mouse press events ARE accompanied
 *  by the correct modifiers ({@link sun.lwawt.macosx.NSEvent#nsToJavaModifiers} returns correct values).
 */
public class MouseMacTouchPressEventModifiers
{
    /**
     * How it works:
     * 1. Send a native mouse press to {@code frame} via
     *    {@link sun.lwawt.macosx.CPlatformResponder#handleMouseEvent(int, int, int, int, int, int, int, int)}
     *    (using reflection).
     * 2. Wait (via {@link Future#get()}) until it generates a usual java MouseEvent
     *    and dispatches it to the MouseListener of the {@code frame}.
     * 3. Verify the dispatched MouseEvent contains correct modifiers, modifiersEx and button number.
     * 4. Do all the steps above but for a corresponding mouse release.
     */
    public static void main(String[] args) throws Throwable {
        // TreeMap to preserve the testing order
        final var testCases = new TreeMap<>(Map.of(
            CocoaConstants.kCGMouseButtonLeft, new MouseEventFieldsToTest(MouseEvent.BUTTON1_MASK, MouseEvent.BUTTON1_DOWN_MASK, MouseEvent.BUTTON1),
            CocoaConstants.kCGMouseButtonRight, new MouseEventFieldsToTest(MouseEvent.BUTTON3_MASK, MouseEvent.BUTTON3_DOWN_MASK, MouseEvent.BUTTON3),
            CocoaConstants.kCGMouseButtonCenter, new MouseEventFieldsToTest(MouseEvent.BUTTON2_MASK, MouseEvent.BUTTON2_DOWN_MASK, MouseEvent.BUTTON2)
        ));

        SwingUtilities.invokeAndWait(MouseMacTouchPressEventModifiers::createAndShowGUI);

        try {
            for (var testCase : testCases.entrySet()) {
                final var fieldsToTest = testCase.getValue();

                final int mouseX = (frame.getWidth() - 1) / 2;
                final int mouseY = (frame.getHeight() - 1) / 2;

                // press

                MouseEvent event = frame.sendNativeMousePress(
                    0,
                    testCase.getKey(),
                    1,
                    mouseX,
                    mouseY
                ).get(500, TimeUnit.MILLISECONDS);
                System.out.println("A mouse press turned into: " + event);

                frame.checkInternalErrors();

                checkMouseEvent(event,
                    MouseEvent.MOUSE_PRESSED, fieldsToTest.modifiers, fieldsToTest.pressModifiersEx, fieldsToTest.button);

                // release

                event = frame.sendNativeMouseRelease(
                    0,
                    testCase.getKey(),
                    1,
                    mouseX,
                    mouseY
                ).get(500, TimeUnit.MILLISECONDS);
                System.out.println("A mouse release turned into: " + event);

                frame.checkInternalErrors();

                checkMouseEvent(event,
                    MouseEvent.MOUSE_RELEASED, fieldsToTest.modifiers, 0, fieldsToTest.button);

                System.out.println();
            }
        } finally {
            SwingUtilities.invokeAndWait(MouseMacTouchPressEventModifiers::disposeGUI);
            System.out.flush();
        }
    }


    private record MouseEventFieldsToTest(int modifiers, int pressModifiersEx, int button) {}

    private static MyFrame frame;

    private static void createAndShowGUI() {
        frame = new MyFrame();
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

        frame.pack();
        frame.setSize(800, 500);

        frame.setLocationRelativeTo(null);
        frame.setAlwaysOnTop(true);

        frame.setVisible(true);
    }

    private static void disposeGUI() {
        if (frame != null) {
            frame.dispose();
        }
    }

    private static void checkMouseEvent(MouseEvent me,
        int expectedId, int expectedModifiers, int expectedModifiersEx, int expectedButton
    ) {
        boolean wrong = false;

        final var errMsg = new StringBuilder(1024);
        errMsg.append("Wrong MouseEvent ").append(me).append(':');

        if (me.getID() != expectedId) {
            errMsg.append("\n  eventId: expected <").append(expectedId).append(">, actual <").append(me.getID()).append('>');
            wrong = true;
        }
        if (me.getModifiers() != expectedModifiers) {
            errMsg.append("\n  modifiers: expected <").append(expectedModifiers).append(">, actual <").append(me.getModifiers()).append('>');
            wrong = true;
        }
        if (me.getModifiersEx() != expectedModifiersEx) {
            errMsg.append("\n  modifiersEx: expected <").append(expectedModifiersEx).append(">, actual <").append(me.getModifiersEx()).append('>');
            wrong = true;
        }
        if (me.getButton() != expectedButton) {
            errMsg.append("\n  button: expected <").append(expectedButton).append(">, actual <").append(me.getButton()).append('>');
            wrong = true;
        }

        if (wrong) {
            throw new IllegalArgumentException(errMsg.append('\n').toString());
        }
    }
}


class MyFrame extends JFrame {
    public MyFrame() {
        addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent e) {
                System.out.println("MyFrame::mousePressed: " + e);
                keepPromiseVia(e);
            }

            @Override
            public void mouseReleased(MouseEvent e) {
                System.out.println("MyFrame::mouseReleased: " + e);
                keepPromiseVia(e);
            }
        });
    }

    public Future<MouseEvent> sendNativeMousePress(int modifierFlags, int buttonNumber, int clickCount, int x, int y) {
        final int eventType = (buttonNumber == CocoaConstants.kCGMouseButtonLeft) ? CocoaConstants.NSEventTypeLeftMouseDown
                              : (buttonNumber == CocoaConstants.kCGMouseButtonRight) ? CocoaConstants.NSEventTypeRightMouseDown
                              : CocoaConstants.NSEventTypeOtherMouseDown;

        return sendNativeMouseEvent(eventType, modifierFlags, buttonNumber, clickCount, x, y, getX() + x, getY() + y);
    }

    public Future<MouseEvent> sendNativeMouseRelease(int modifierFlags, int buttonNumber, int clickCount, int x, int y) {
        final int eventType = (buttonNumber == CocoaConstants.kCGMouseButtonLeft) ? CocoaConstants.NSEventTypeLeftMouseUp
                              : (buttonNumber == CocoaConstants.kCGMouseButtonRight) ? CocoaConstants.NSEventTypeRightMouseUp
                              : CocoaConstants.NSEventTypeOtherMouseUp;

        return sendNativeMouseEvent(eventType, modifierFlags, buttonNumber, clickCount, x, y, getX() + x, getY() + y);
    }

    public void checkInternalErrors() throws Throwable {
        final Throwable result = internalError.getAndSet(null);
        if (result != null) {
            throw result;
        }
    }


    private final AtomicReference<CompletableFuture<MouseEvent>> mouseEventPromise = new AtomicReference<>(null);

    private final AtomicReference<Throwable> internalError = new AtomicReference<>(null);

    private Future<MouseEvent> sendNativeMouseEvent(
        final int eventType,
        final int modifierFlags,
        final int buttonNumber,
        final int clickCount,
        final int x,
        final int y,
        final int absX,
        final int absY
    ) {
        assert !SwingUtilities.isEventDispatchThread();
        assert mouseEventPromise.get() == null : "Trying to send a mouse event while there is already a processing one";

        final CompletableFuture<MouseEvent> result = new CompletableFuture<>();

        SwingUtilities.invokeLater(() -> {
            try {
                LWCToolkit.invokeLater(() -> {
                    try {
                        final Object thisPlatformResponder = obtainFramePlatformResponder(this);
                        final Method thisPlatformResponderHandleMouseEventMethod = obtainHandleMouseEventMethod(thisPlatformResponder);

                        if (mouseEventPromise.compareAndExchange(null, result) != null) {
                            throw new IllegalStateException("Trying to send a mouse event while there is already a processing one");
                        }

                        thisPlatformResponderHandleMouseEventMethod.invoke(thisPlatformResponder,
                            eventType, modifierFlags, buttonNumber, clickCount, x, y, absX, absY);
                    } catch (Throwable err) {
                        // Remove the promise if thisPlatformResponderHandleMouseEventMethod.invoke(...) failed
                        mouseEventPromise.compareAndExchange(result, null);
                        failPromiseDueTo(result, err);
                    }
                }, this);
            } catch (Throwable err) {
                failPromiseDueTo(result, err);
            }
        });

        return result;
    }

    /** Wraps {@link CompletableFuture#complete(Object)} */
    private void keepPromiseVia(MouseEvent mouseEvent) {
        try {
            final CompletableFuture<MouseEvent> promise = mouseEventPromise.getAndSet(null);
            if (promise == null) {
                throw new IllegalStateException("The following unexpected MouseEvent has arrived: " + mouseEvent);
            }

            if (!promise.complete(mouseEvent)) {
                throw new IllegalStateException("The promise had already been completed when the following MouseEvent arrived: " + mouseEvent);
            }
        } catch (Throwable err) {
            setInternalError(err);
        }
    }

    /** Wraps {@link CompletableFuture#completeExceptionally(Throwable)} */
    private void failPromiseDueTo(CompletableFuture<MouseEvent> promise, Throwable cause) {
        try {
            if (!promise.completeExceptionally(cause)) {
                throw new IllegalStateException("The promise had already been completed when the following error arrived: " + cause);
            }
        } catch (Throwable err) {
            setInternalError(err);
        }
    }

    private void setInternalError(Throwable err) {
        if (internalError.compareAndExchange(null, err) != null) {
            System.err.println("Failed to set the following internal error because there is another one: " + err);
        }
    }

    /** Obtains {@code component.peer.platformWindow.responder} */
    private static Object obtainFramePlatformResponder(Component component) throws NoSuchFieldException, IllegalAccessException {
        final Object framePeer;
        {
            final var frameClass = Component.class;
            final var peerField = frameClass.getDeclaredField("peer");

            peerField.setAccessible(true);

            framePeer = peerField.get(component);
        }

        final Object peerPlatformWindow;
        {
            final var peerClass = framePeer.getClass();
            final var platformWindowField = peerClass.getDeclaredField("platformWindow");

            platformWindowField.setAccessible(true);

            peerPlatformWindow = platformWindowField.get(framePeer);
        }

        final Object platformWindowResponder;
        {
            final var peerPlatformWindowClass = peerPlatformWindow.getClass();
            final var platformWindowResponderField = peerPlatformWindowClass.getDeclaredField("responder");

            platformWindowResponderField.setAccessible(true);

            platformWindowResponder = platformWindowResponderField.get(peerPlatformWindow);
        }

        return platformWindowResponder;
    }

    /** Obtains {@link sun.lwawt.macosx.CPlatformResponder#handleMouseEvent(int, int, int, int, int, int, int, int)} */
    private static Method obtainHandleMouseEventMethod(final Object platformResponder) throws NoSuchMethodException {
        final var responderClass = platformResponder.getClass();
        final var handleMouseEventMethod = responderClass.getDeclaredMethod(
            "handleMouseEvent",
            int.class, int.class, int.class, int.class, int.class, int.class, int.class, int.class
        );

        handleMouseEventMethod.setAccessible(true);

        return handleMouseEventMethod;
    }
}
