/*
 * Copyright (c) 2014, 2024, 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.AWTException;
import java.awt.Robot;
import java.awt.GraphicsDevice;
import java.awt.Toolkit;
import java.awt.Point;
import java.awt.MouseInfo;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;

/**
 * ExtendedRobot is a subclass of {@link java.awt.Robot}. It provides some convenience methods that are
 * ought to be moved to {@link java.awt.Robot} class.
 * <p>
 * ExtendedRobot uses delay {@link #getSyncDelay()} to make syncing threads with {@link #waitForIdle()}
 * more stable. This delay can be set once on creating object and could not be changed throughout object
 * lifecycle. Constructor reads vm integer property {@code java.awt.robotdelay} and sets the delay value
 * equal to the property value. If the property was not set 500 milliseconds default value is used.
 * <p>
 * When using jtreg you would include this class via something like:
 * <pre>
 * {@literal @}library ../../../../lib/testlibrary
 * {@literal @}build ExtendedRobot
 * </pre>
 *
 * @author      Dmitriy Ermashov
 * @since       9
 */

public class ExtendedRobot extends Robot {

    private static int DEFAULT_SPEED = 20;       // Speed for mouse glide and click
    private static int DEFAULT_SYNC_DELAY = 500; // Default Additional delay for waitForIdle()
    private static int DEFAULT_STEP_LENGTH = 2;  // Step length (in pixels) for mouse glide

    private final int syncDelay = DEFAULT_SYNC_DELAY;

    /**
     * Constructs an ExtendedRobot object in the coordinate system of the primary screen.
     *
     * @throws  AWTException if the platform configuration does not allow low-level input
     *          control. This exception is always thrown when
     *          GraphicsEnvironment.isHeadless() returns true
     *
     * @see     java.awt.GraphicsEnvironment#isHeadless
     */
    public ExtendedRobot() throws AWTException {
        super();
    }

    /**
     * Creates an ExtendedRobot for the given screen device. Coordinates passed
     * to ExtendedRobot method calls like mouseMove and createScreenCapture will
     * be interpreted as being in the same coordinate system as the specified screen.
     * Note that depending on the platform configuration, multiple screens may either:
     * <ul>
     * <li>share the same coordinate system to form a combined virtual screen</li>
     * <li>use different coordinate systems to act as independent screens</li>
     * </ul>
     * This constructor is meant for the latter case.
     * <p>
     * If screen devices are reconfigured such that the coordinate system is
     * affected, the behavior of existing ExtendedRobot objects is undefined.
     *
     * @param   screen  A screen GraphicsDevice indicating the coordinate
     *                  system the Robot will operate in.
     * @throws  AWTException if the platform configuration does not allow low-level input
     *          control. This exception is always thrown when
     *          GraphicsEnvironment.isHeadless() returns true.
     * @throws  IllegalArgumentException if {@code screen} is not a screen
     *          GraphicsDevice.
     *
     * @see     java.awt.GraphicsEnvironment#isHeadless
     * @see     GraphicsDevice
     */
    public ExtendedRobot(GraphicsDevice screen) throws AWTException {
        super(screen);
    }

    /**
     * Returns delay length for {@link #waitForIdle()} method
     *
     * @return  Current delay value
     *
     * @see     #waitForIdle()
     */
    public int getSyncDelay(){ return this.syncDelay; }

    /**
     * Clicks mouse button(s) by calling {@link java.awt.Robot#mousePress(int)} and
     * {@link java.awt.Robot#mouseRelease(int)} methods
     *
     *
     * @param   buttons The button mask; a combination of one or more mouse button masks.
     * @throws  IllegalArgumentException if the {@code buttons} mask contains the mask for
     *          extra mouse button and support for extended mouse buttons is
     *          {@link Toolkit#areExtraMouseButtonsEnabled() disabled} by Java
     * @throws  IllegalArgumentException if the {@code buttons} mask contains the mask for
     *          extra mouse button that does not exist on the mouse and support for extended
     *          mouse buttons is {@link Toolkit#areExtraMouseButtonsEnabled() enabled}
     *          by Java
     *
     * @see     #mousePress(int)
     * @see     #mouseRelease(int)
     * @see     InputEvent#getMaskForButton(int)
     * @see     Toolkit#areExtraMouseButtonsEnabled()
     * @see     java.awt.event.MouseEvent
     */
    public void click(int buttons) {
        mousePress(buttons);
        waitForIdle(DEFAULT_SPEED);
        mouseRelease(buttons);
        waitForIdle();
    }

    /**
     * Clicks mouse button 1
     *
     * @throws  IllegalArgumentException if the {@code buttons} mask contains the mask for
     *          extra mouse button and support for extended mouse buttons is
     *          {@link Toolkit#areExtraMouseButtonsEnabled() disabled} by Java
     * @throws  IllegalArgumentException if the {@code buttons} mask contains the mask for
     *          extra mouse button that does not exist on the mouse and support for extended
     *          mouse buttons is {@link Toolkit#areExtraMouseButtonsEnabled() enabled}
     *          by Java
     *
     * @see     #click(int)
     */
    public void click() {
        click(InputEvent.BUTTON1_DOWN_MASK);
    }

    /**
     * Waits until all events currently on the event queue have been processed with given
     * delay after syncing threads. It uses more advanced method of synchronizing threads
     * unlike {@link java.awt.Robot#waitForIdle()}
     *
     * @param   delayValue  Additional delay length in milliseconds to wait until thread
     *                      sync been completed
     * @throws  sun.awt.SunToolkit.IllegalThreadException if called on the AWT event
     *          dispatching thread
     */
    public synchronized void waitForIdle(int delayValue) {
        super.waitForIdle();
        delay(delayValue);
    }

    /**
     * Waits until all events currently on the event queue have been processed with delay
     * {@link #getSyncDelay()} after syncing threads. It uses more advanced method of
     * synchronizing threads unlike {@link java.awt.Robot#waitForIdle()}
     *
     * @throws  sun.awt.SunToolkit.IllegalThreadException if called on the AWT event
     *          dispatching thread
     *
     * @see     #waitForIdle(int)
     */
    @Override
    public synchronized void waitForIdle() {
        waitForIdle(syncDelay);
    }

    /**
     * Move the mouse in multiple steps from where it is
     * now to the destination coordinates.
     *
     * @param   x   Destination point x coordinate
     * @param   y   Destination point y coordinate
     *
     * @see     #glide(int, int, int, int)
     */
    public void glide(int x, int y) {
        Point p = MouseInfo.getPointerInfo().getLocation();
        glide(p.x, p.y, x, y);
    }

    /**
     * Move the mouse in multiple steps from where it is
     * now to the destination point.
     *
     * @param   dest    Destination point
     *
     * @see     #glide(int, int)
     */
    public void glide(Point dest) {
        glide(dest.x, dest.y);
    }

    /**
     * Move the mouse in multiple steps from source coordinates
     * to the destination coordinates.
     *
     * @param   fromX   Source point x coordinate
     * @param   fromY   Source point y coordinate
     * @param   toX     Destination point x coordinate
     * @param   toY     Destination point y coordinate
     *
     * @see     #glide(int, int, int, int, int, int)
     */
    public void glide(int fromX, int fromY, int toX, int toY) {
        glide(fromX, fromY, toX, toY, DEFAULT_STEP_LENGTH, DEFAULT_SPEED);
    }

    /**
     * Move the mouse in multiple steps from source point to the
     * destination point with default speed and step length.
     *
     * @param   src     Source point
     * @param   dest    Destination point
     *
     * @see     #glide(int, int, int, int, int, int)
     */
    public void glide(Point src, Point dest) {
        glide(src.x, src.y, dest.x, dest.y, DEFAULT_STEP_LENGTH, DEFAULT_SPEED);
    }

    /**
     * Move the mouse in multiple steps from source point to the
     * destination point with given speed and step length.
     *
     * @param   srcX        Source point x cordinate
     * @param   srcY        Source point y cordinate
     * @param   destX       Destination point x cordinate
     * @param   destY       Destination point y cordinate
     * @param   stepLength  Approximate length of one step
     * @param   speed       Delay between steps.
     *
     * @see     #mouseMove(int, int)
     * @see     #delay(int)
     */
     public void glide(int srcX, int srcY, int destX, int destY, int stepLength, int speed) {
        int stepNum;
        double tDx, tDy;
        double dx, dy, ds;
        double x, y;

        dx = (destX - srcX);
        dy = (destY - srcY);
        ds = Math.sqrt(dx*dx + dy*dy);

        tDx = dx / ds * stepLength;
        tDy = dy / ds * stepLength;

        int stepsCount = (int) ds / stepLength;

        // Walk the mouse to the destination one step at a time
        mouseMove(srcX, srcY);

        for (x = srcX, y = srcY, stepNum = 0;
             stepNum < stepsCount;
             stepNum++) {
            x += tDx;
            y += tDy;
            mouseMove((int)x, (int)y);
            delay(speed);
        }

        // Ensure the mouse moves to the right destination.
        // The steps may have led the mouse to a slightly wrong place.
        mouseMove(destX, destY);
    }

    /**
     * Moves mouse pointer to given screen coordinates.
     *
     * @param   position    Target position
     *
     * @see     java.awt.Robot#mouseMove(int, int)
     */
    public synchronized void mouseMove(Point position) {
        mouseMove(position.x, position.y);
    }


    /**
     * Emulate native drag and drop process using {@code InputEvent.BUTTON1_DOWN_MASK}.
     * The method successively moves mouse cursor to point with coordinates
     * ({@code fromX}, {@code fromY}), presses mouse button 1, drag mouse to
     * point with coordinates ({@code toX}, {@code toY}) and releases mouse
     * button 1 at last.
     *
     * @param   fromX   Source point x coordinate
     * @param   fromY   Source point y coordinate
     * @param   toX     Destination point x coordinate
     * @param   toY     Destination point y coordinate
     *
     * @see     #mousePress(int)
     * @see     #glide(int, int, int, int)
     */
    public void dragAndDrop(int fromX, int fromY, int toX, int toY){
        mouseMove(fromX, fromY);
        mousePress(InputEvent.BUTTON1_DOWN_MASK);
        waitForIdle();
        glide(toX, toY);
        mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
        waitForIdle();
    }

    /**
     * Emulate native drag and drop process using {@code InputEvent.BUTTON1_DOWN_MASK}.
     * The method successively moves mouse cursor to point {@code from},
     * presses mouse button 1, drag mouse to point {@code to} and releases
     * mouse button 1 at last.
     *
     * @param   from    Source point
     * @param   to      Destination point
     *
     * @see     #mousePress(int)
     * @see     #glide(int, int, int, int)
     * @see     #dragAndDrop(int, int, int, int)
     */
    public void dragAndDrop(Point from, Point to){
        dragAndDrop(from.x, from.y, to.x, to.y);
    }

    /**
     * Successively presses and releases a given key.
     * <p>
     * Key codes that have more than one physical key associated with them
     * (e.g. {@code KeyEvent.VK_SHIFT} could mean either the
     * left or right shift key) will map to the left key.
     *
     * @param   keycode Key to press (e.g. {@code KeyEvent.VK_A})
     * @throws  IllegalArgumentException if {@code keycode} is not
     *          a valid key
     *
     * @see     java.awt.Robot#keyPress(int)
     * @see     java.awt.Robot#keyRelease(int)
     * @see     java.awt.event.KeyEvent
     */
    public void type(int keycode) {
        keyPress(keycode);
        waitForIdle(DEFAULT_SPEED);
        keyRelease(keycode);
        waitForIdle(DEFAULT_SPEED);
    }

    /**
     * Types given character
     *
     * @param   c   Character to be typed (e.g. {@code 'a'})
     *
     * @see     #type(int)
     * @see     java.awt.event.KeyEvent
     */
    public void type(char c) {
        type(KeyEvent.getExtendedKeyCodeForChar(c));
    }

    /**
     * Types given array of characters one by one
     *
     * @param   symbols Array of characters to be typed
     *
     * @see     #type(char)
     */
    public void type(char[] symbols) {
        for (int i = 0; i < symbols.length; i++) {
            type(symbols[i]);
        }
    }

    /**
     * Types given string
     *
     * @param   s   String to be typed
     *
     * @see     #type(char[])
     */
    public void type(String s) {
        type(s.toCharArray());
    }
}
