/*
 * Copyright 2006-2007 Sun Microsystems, Inc.  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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package test.java.awt.regtesthelpers;
/**
 * <p>This class contains utilities useful for regression testing.
 * <p>When using jtreg you would include this class into the build
 * list via something like:
 * <pre>
     @library ../../../regtesthelpers
     @build Util
     @run main YourTest
   </pre>
 * Note that if you are about to create a test based on
 * Applet-template, then put those lines into html-file, not in java-file.
 * <p> And put an
 * import test.java.awt.regtesthelpers.Util;
 * into the java source of test.
*/

import java.awt.Component;
import java.awt.Frame;
import java.awt.Dialog;
import java.awt.Window;
import java.awt.Button;
import java.awt.Point;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.IllegalComponentStateException;
import java.awt.AWTException;
import java.awt.AWTEvent;

import java.awt.event.InputEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.ActionEvent;
import java.awt.event.FocusEvent;
import java.awt.event.WindowListener;
import java.awt.event.WindowFocusListener;
import java.awt.event.FocusListener;
import java.awt.event.ActionListener;

import java.awt.peer.FramePeer;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import java.security.PrivilegedAction;
import java.security.AccessController;

import java.util.concurrent.atomic.AtomicBoolean;

public final class Util {
    private Util() {} // this is a helper class with static methods :)

    /*
     * @throws RuntimeException when creation failed
     */
    public static Robot createRobot() {
        try {
            return new Robot();
        } catch (AWTException e) {
            throw new RuntimeException("Error: unable to create robot", e);
        }
    }

    public static Frame createEmbeddedFrame(final Frame embedder)
        throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException, NoSuchMethodException,
               InstantiationException, InvocationTargetException
    {
        Toolkit tk = Toolkit.getDefaultToolkit();
        FramePeer frame_peer = (FramePeer) embedder.getPeer();
        System.out.println("frame's peer = " + frame_peer);
        if ("sun.awt.windows.WToolkit".equals(tk.getClass().getName())) {
            Class comp_peer_class =
                Class.forName("sun.awt.windows.WComponentPeer");
            System.out.println("comp peer class = " + comp_peer_class);
            Field hwnd_field = comp_peer_class.getDeclaredField("hwnd");
            hwnd_field.setAccessible(true);
            System.out.println("hwnd_field =" + hwnd_field);
            long hwnd = hwnd_field.getLong(frame_peer);
            System.out.println("hwnd = " + hwnd);

            Class clazz = Class.forName("sun.awt.windows.WEmbeddedFrame");
            Constructor constructor = clazz.getConstructor (new Class [] {Long.TYPE});
            return (Frame) constructor.newInstance (new Object[] {hwnd});
        } else if ("sun.awt.X11.XToolkit".equals(tk.getClass().getName())) {
            Class x_base_window_class = Class.forName("sun.awt.X11.XBaseWindow");
            System.out.println("x_base_window_class = " + x_base_window_class);
            Method get_window = x_base_window_class.getMethod("getWindow", new Class[0]);
            System.out.println("get_window = " + get_window);
            long window = (Long) get_window.invoke(frame_peer, new Object[0]);
            System.out.println("window = " + window);
            Class clazz = Class.forName("sun.awt.X11.XEmbeddedFrame");
            Constructor constructor = clazz.getConstructor (new Class [] {Long.TYPE, Boolean.TYPE});
            return (Frame) constructor.newInstance (new Object[] {window, true});
        }

        throw new RuntimeException("Unexpected toolkit - " + tk);
    }

    /**
     * Moves mouse pointer in the center of given {@code comp} component
     * using {@code robot} parameter.
     */
    public static void pointOnComp(final Component comp, final Robot robot) {
        Rectangle bounds = new Rectangle(comp.getLocationOnScreen(), comp.getSize());
        robot.mouseMove(bounds.x + bounds.width / 2, bounds.y + bounds.height / 2);
    }

    /**
     * Moves mouse pointer in the center of a given {@code comp} component
     * and performs a left mouse button click using the {@code robot} parameter
     * with the {@code delay} delay between press and release.
     */
    public static void clickOnComp(final Component comp, final Robot robot, int delay) {
        pointOnComp(comp, robot);
        robot.delay(delay);
        robot.mousePress(InputEvent.BUTTON1_MASK);
        robot.delay(delay);
        robot.mouseRelease(InputEvent.BUTTON1_MASK);
    }

    /**
     * Moves mouse pointer in the center of a given {@code comp} component
     * and performs a left mouse button click using the {@code robot} parameter
     * with the default delay between press and release.
     */
    public static void clickOnComp(final Component comp, final Robot robot) {
        clickOnComp(comp, robot, 50);
    }

    /*
     * Clicks on a title of Frame/Dialog.
     * WARNING: it may fail on some platforms when the window is not wide enough.
     */
    public static void clickOnTitle(final Window decoratedWindow, final Robot robot) {
        Point p = decoratedWindow.getLocationOnScreen();
        Dimension d = decoratedWindow.getSize();

        if (decoratedWindow instanceof Frame || decoratedWindow instanceof Dialog) {
            robot.mouseMove(p.x + (int)(d.getWidth()/2), p.y + (int)decoratedWindow.getInsets().top/2);
            robot.delay(50);
            robot.mousePress(InputEvent.BUTTON1_MASK);
            robot.delay(50);
            robot.mouseRelease(InputEvent.BUTTON1_MASK);
        }
    }

    public static void waitForIdle(final Robot robot) {
        // we do not use robot for now, use SunToolkit.realSync() instead
        ((sun.awt.SunToolkit)Toolkit.getDefaultToolkit()).realSync();
    }

    public static Field getField(final Class klass, final String fieldName) {
        return AccessController.doPrivileged(new PrivilegedAction<Field>() {
            public Field run() {
                try {
                    Field field = klass.getDeclaredField(fieldName);
                    assert (field != null);
                    field.setAccessible(true);
                    return field;
                } catch (SecurityException se) {
                    throw new RuntimeException("Error: unexpected exception caught!", se);
                } catch (NoSuchFieldException nsfe) {
                    throw new RuntimeException("Error: unexpected exception caught!", nsfe);
                }
            }
        });
    }

    /*
     * Waits for a notification and for a boolean condition to become true.
     * The method returns when the above conditions are fullfilled or when the timeout
     * occurs.
     *
     * @param condition the object to be notified and the booelan condition to wait for
     * @param timeout the maximum time to wait in milliseconds
     * @param catchExceptions if {@code true} the method catches InterruptedException
     * @return the final boolean value of the {@code condition}
     * @throws InterruptedException if the awaiting proccess has been interrupted
     */
    public static boolean waitForConditionEx(final AtomicBoolean condition, long timeout)
      throws InterruptedException
        {
            synchronized (condition) {
                long startTime = System.currentTimeMillis();
                while (!condition.get()) {
                    condition.wait(timeout);
                    if (System.currentTimeMillis() - startTime >= timeout ) {
                        break;
                    }
                }
            }
            return condition.get();
        }

    /*
     * The same as {@code waitForConditionEx(AtomicBoolean, long)} except that it
     * doesn't throw InterruptedException.
     */
    public static boolean waitForCondition(final AtomicBoolean condition, long timeout) {
        try {
            return waitForConditionEx(condition, timeout);
        } catch (InterruptedException e) {
            throw new RuntimeException("Error: unexpected exception caught!", e);
        }
    }

    /*
     * The same as {@code waitForConditionEx(AtomicBoolean, long)} but without a timeout.
     */
    public static void waitForConditionEx(final AtomicBoolean condition)
      throws InterruptedException
        {
            synchronized (condition) {
                while (!condition.get()) {
                    condition.wait();
                }
            }
        }

    /*
     * The same as {@code waitForConditionEx(AtomicBoolean)} except that it
     * doesn't throw InterruptedException.
     */
    public static void waitForCondition(final AtomicBoolean condition) {
        try {
            waitForConditionEx(condition);
        } catch (InterruptedException e) {
            throw new RuntimeException("Error: unexpected exception caught!", e);
        }
    }

    public static void waitTillShownEx(final Component comp) throws InterruptedException {
        while (true) {
            try {
                Thread.sleep(100);
                comp.getLocationOnScreen();
                break;
            } catch (IllegalComponentStateException e) {}
        }
    }
    public static void waitTillShown(final Component comp) {
        try {
            waitTillShownEx(comp);
        } catch (InterruptedException e) {
            throw new RuntimeException("Error: unexpected exception caught!", e);
        }
    }

    /**
     * Drags from one point to another with the specified mouse button pressed.
     *
     * @param robot a robot to use for moving the mouse, etc.
     * @param startPoint a start point of the drag
     * @param endPoint an end point of the drag
     * @param button one of {@code InputEvent.BUTTON1_MASK},
     *     {@code InputEvent.BUTTON2_MASK}, {@code InputEvent.BUTTON3_MASK}
     *
     * @throws IllegalArgumentException if {@code button} is not one of
     *     {@code InputEvent.BUTTON1_MASK}, {@code InputEvent.BUTTON2_MASK},
     *     {@code InputEvent.BUTTON3_MASK}
     */
    public static void drag(Robot robot, Point startPoint, Point endPoint, int button) {
        if (!(button == InputEvent.BUTTON1_MASK || button == InputEvent.BUTTON2_MASK
                || button == InputEvent.BUTTON3_MASK))
        {
            throw new IllegalArgumentException("invalid mouse button");
        }

        robot.mouseMove(startPoint.x, startPoint.y);
        robot.mousePress(button);
        try {
            mouseMove(robot, startPoint, endPoint);
        } finally {
            robot.mouseRelease(button);
        }
    }

    /**
     * Moves the mouse pointer from one point to another.
     * Uses Bresenham's algorithm.
     *
     * @param robot a robot to use for moving the mouse
     * @param startPoint a start point of the drag
     * @param endPoint an end point of the drag
     */
    public static void mouseMove(Robot robot, Point startPoint, Point endPoint) {
        int dx = endPoint.x - startPoint.x;
        int dy = endPoint.y - startPoint.y;

        int ax = Math.abs(dx) * 2;
        int ay = Math.abs(dy) * 2;

        int sx = signWOZero(dx);
        int sy = signWOZero(dy);

        int x = startPoint.x;
        int y = startPoint.y;

        int d = 0;

        if (ax > ay) {
            d = ay - ax/2;
            while (true){
                robot.mouseMove(x, y);
                robot.delay(50);

                if (x == endPoint.x){
                    return;
                }
                if (d >= 0){
                    y = y + sy;
                    d = d - ax;
                }
                x = x + sx;
                d = d + ay;
            }
        } else {
            d = ax - ay/2;
            while (true){
                robot.mouseMove(x, y);
                robot.delay(50);

                if (y == endPoint.y){
                    return;
                }
                if (d >= 0){
                    x = x + sx;
                    d = d - ay;
                }
                y = y + sy;
                d = d + ax;
            }
        }
    }

    private static int signWOZero(int i){
        return (i > 0)? 1: -1;
    }

    private static int sign(int n) {
        return n < 0 ? -1 : n == 0 ? 0 : 1;
    }

    /** Returns {@code WindowListener} instance that diposes {@code Window} on
     *  "window closing" event.
     *
     * @return    the {@code WindowListener} instance that could be set
     *            on a {@code Window}. After that
     *            the {@code Window} is disposed when "window closed"
     *            event is sent to the {@code Window}
     */
    public static WindowListener getClosingWindowAdapter() {
        return new WindowAdapter () {
            public void windowClosing(WindowEvent e) {
                e.getWindow().dispose();
            }
        };
    }

    /*
     * The values directly map to the ones of
     * sun.awt.X11.XWM & sun.awt.motif.MToolkit classes.
     */
    public final static int
        UNDETERMINED_WM = 1,
        NO_WM = 2,
        OTHER_WM = 3,
        OPENLOOK_WM = 4,
        MOTIF_WM = 5,
        CDE_WM = 6,
        ENLIGHTEN_WM = 7,
        KDE2_WM = 8,
        SAWFISH_WM = 9,
        ICE_WM = 10,
        METACITY_WM = 11,
        COMPIZ_WM = 12,
        LG3D_WM = 13;

    /*
     * Returns -1 in case of not X Window or any problems.
     */
    public static int getWMID() {
        Class clazz = null;
        try {
            if ("sun.awt.X11.XToolkit".equals(Toolkit.getDefaultToolkit().getClass().getName())) {
                clazz = Class.forName("sun.awt.X11.XWM");
            } else if ("sun.awt.motif.MToolkit".equals(Toolkit.getDefaultToolkit().getClass().getName())) {
                clazz = Class.forName("sun.awt.motif.MToolkit");
            }
        } catch (ClassNotFoundException cnfe) {
            cnfe.printStackTrace();
        }
        if (clazz == null) {
            return -1;
        }

        try {
            final Class _clazz = clazz;
            Method m_getWMID = (Method)AccessController.doPrivileged(new PrivilegedAction() {
                    public Object run() {
                        try {
                            Method method = _clazz.getDeclaredMethod("getWMID", new Class[] {});
                            if (method != null) {
                                method.setAccessible(true);
                            }
                            return method;
                        } catch (NoSuchMethodException e) {
                            assert false;
                        } catch (SecurityException e) {
                            assert false;
                        }
                        return null;
                    }
                });
            return ((Integer)m_getWMID.invoke(null, new Object[] {})).intValue();
        } catch (IllegalAccessException iae) {
            iae.printStackTrace();
        } catch (InvocationTargetException ite) {
            ite.printStackTrace();
        }
        return -1;
    }


    ////////////////////////////
    // Some stuff to test focus.
    ////////////////////////////

    private static WindowGainedFocusListener wgfListener = new WindowGainedFocusListener();
    private static FocusGainedListener fgListener = new FocusGainedListener();
    private static ActionPerformedListener apListener = new ActionPerformedListener();

    private abstract static class EventListener {
        AtomicBoolean notifier = new AtomicBoolean(false);
        Component comp;
        boolean printEvent;

        public void listen(Component comp, boolean printEvent) {
            this.comp = comp;
            this.printEvent = printEvent;
            notifier.set(false);
            setListener(comp);
        }

        public AtomicBoolean getNotifier() {
            return notifier;
        }

        abstract void setListener(Component comp);

        void printAndNotify(AWTEvent e) {
            if (printEvent) {
                System.err.println(e);
            }
            synchronized (notifier) {
                notifier.set(true);
                notifier.notifyAll();
            }
        }
    }

    private static class WindowGainedFocusListener extends EventListener implements WindowFocusListener {

        void setListener(Component comp) {
            ((Window)comp).addWindowFocusListener(this);
        }

        public void windowGainedFocus(WindowEvent e) {

            ((Window)comp).removeWindowFocusListener(this);
            printAndNotify(e);
        }

        public void windowLostFocus(WindowEvent e) {}
    }

    private static class FocusGainedListener extends EventListener implements FocusListener {

        void setListener(Component comp) {
            comp.addFocusListener(this);
        }

        public void focusGained(FocusEvent e) {
            comp.removeFocusListener(this);
            printAndNotify(e);
        }

        public void focusLost(FocusEvent e) {}
    }

    private static class ActionPerformedListener extends EventListener implements ActionListener {

        void setListener(Component comp) {
            ((Button)comp).addActionListener(this);
        }

        public void actionPerformed(ActionEvent e) {
            ((Button)comp).removeActionListener(this);
            printAndNotify(e);
        }
    }

    private static boolean trackEvent(int eventID, Component comp, Runnable action, int time, boolean printEvent) {
        EventListener listener = null;

        switch (eventID) {
        case WindowEvent.WINDOW_GAINED_FOCUS:
            listener = wgfListener;
            break;
        case FocusEvent.FOCUS_GAINED:
            listener = fgListener;
            break;
        case ActionEvent.ACTION_PERFORMED:
            listener = apListener;
            break;
        }

        listener.listen(comp, printEvent);
        action.run();
        return Util.waitForCondition(listener.getNotifier(), time);
    }

    /*
     * Tracks WINDOW_GAINED_FOCUS event for a window caused by an action.
     * @param window the window to track the event for
     * @param action the action to perform
     * @param time the max time to wait for the event
     * @param printEvent should the event received be printed or doesn't
     * @return true if the event has been received, otherwise false
     */
    public static boolean trackWindowGainedFocus(Window window, Runnable action, int time, boolean printEvent) {
        return trackEvent(WindowEvent.WINDOW_GAINED_FOCUS, window, action, time, printEvent);
    }

    /*
     * Tracks FOCUS_GAINED event for a component caused by an action.
     * @see #trackWindowGainedFocus
     */
    public static boolean trackFocusGained(Component comp, Runnable action, int time, boolean printEvent) {
        return trackEvent(FocusEvent.FOCUS_GAINED, comp, action, time, printEvent);
    }

    /*
     * Tracks ACTION_PERFORMED event for a button caused by an action.
     * @see #trackWindowGainedFocus
     */
    public static boolean trackActionPerformed(Button button, Runnable action, int time, boolean printEvent) {
        return trackEvent(ActionEvent.ACTION_PERFORMED, button, action, time, printEvent);
    }
}
