/*
 * Copyright (c) 2014, 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.*;
import java.awt.event.*;
import java.lang.reflect.InvocationTargetException;
import javax.swing.SwingUtilities;
import java.io.*;

/**
 * AWT Mixing test for HierarchyBoundsListener ancestors.
 * <p>See <a href="https://bugs.openjdk.java.net/browse/JDK-6768230">CR6768230</a> for details.
 */
/*
@test
@bug 6768230
@summary Mixing test for HierarchyBoundsListener ancestors
@build FrameBorderCounter
@run main HierarchyBoundsListenerMixingTest
 */
public class HierarchyBoundsListenerMixingTest {

    protected void prepareControls() {
        dummy = new Frame();
        dummy.setSize(100, 100);
        dummy.setLocation(0, 350);
        dummy.setVisible(true);

        frame = new Frame("Test Frame");
        frame.setLayout(new FlowLayout());

        panel = new Panel();
        button = new Button("Button");
        label = new Label("Label");
        list = new List();
        list.add("One");
        list.add("Two");
        list.add("Three");
        choice = new Choice();
        choice.add("Red");
        choice.add("Orange");
        choice.add("Yellow");
        checkbox = new Checkbox("Checkbox");
        scrollbar = new Scrollbar(Scrollbar.HORIZONTAL, 0, 1, 0, 255);
        textfield = new TextField(15);
        textarea = new TextArea(5, 15);

        components = new Component[] {
            panel, button, label, list, choice, checkbox, scrollbar, textfield, textarea
        };
        ancestorResized = new boolean[components.length];
        ancestorMoved = new boolean[components.length];

        frame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent event) {
                System.err.println("User closed the window");
            }
        });

        HierarchyBoundsListener listener = new HierarchyBoundsListenerImpl();
        for (int i = 0; i < components.length; i++) {
            components[i].addHierarchyBoundsListener(listener);
            frame.add(components[i]);
        }
        frame.setSize(300, 300);
        frame.setVisible(true);
    }

    private int frameBorderCounter() {
        String JAVA_HOME = System.getProperty("java.home");

        try {
            Process p = Runtime.getRuntime().exec(JAVA_HOME + "/bin/java FrameBorderCounter");
            try {
                p.waitFor();
            } catch (InterruptedException e) {
                e.printStackTrace();
                throw new RuntimeException(e);
            }
            if (p.exitValue() != 0) {
                throw new RuntimeException("FrameBorderCounter exited with not null code!\n" + readInputStream(p.getErrorStream()));
            }
            return Integer.parseInt(readInputStream(p.getInputStream()).trim());
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    private String readInputStream(InputStream is) throws IOException {
        byte[] buffer = new byte[4096];
        int len = 0;
        StringBuilder sb = new StringBuilder();
        try (InputStreamReader isr = new InputStreamReader(is)) {
            while ((len = is.read(buffer)) > 0) {
                sb.append(new String(buffer, 0, len));
            }
        }
        return sb.toString();
    }

    protected boolean performTest() {
        int BORDER_SHIFT = frameBorderCounter();
        BORDER_SHIFT = Math.abs(BORDER_SHIFT) == 1 ? BORDER_SHIFT : BORDER_SHIFT / 2;
        Robot robot = null;
        try {
            robot = new Robot();
            Thread.sleep(delay * 10);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("Robot creation exception.");
        }

        robot.mouseMove((int) components[0].getLocationOnScreen().x + components[0].getSize().width / 2,
                        (int) components[0].getLocationOnScreen().y + components[0].getSize().height / 2);
        robot.delay(delay);
        robot.mousePress(InputEvent.BUTTON1_MASK);
        robot.delay(delay);
        robot.mouseRelease(InputEvent.BUTTON1_MASK);
        robot.delay(delay);

        resetValues();
        try {
            EventQueue.invokeAndWait(new Runnable() {
                public void run() {
                    frame.setSize(new Dimension(frame.getSize().width + 10, frame.getSize().height + 10));
                    frame.invalidate();
                    frame.validate();
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
            passed = false;
        }
        if (! resizeTriggered) {
            synchronized (resizeLock) {
                try {
                    resizeLock.wait(delay * 10);
                } catch (Exception e) {
                }
            }
        }
        for (int i = 0; i < components.length; i++) {
            if (! ancestorResized[i]) {
                System.err.println("FAIL: Frame resized using API call. " +
                                   "Ancestor resized event did not occur for " + components[i].getClass());
                passed = false;
            }
        }
        if (moveCount > 0) {
            System.err.println("FAIL: Ancestor moved event occured when Frame resized using API");
            passed = false;
        }
        robot.delay(delay * 5);

        resetValues();
        int x = (int) frame.getLocationOnScreen().x;
        int y = (int) frame.getLocationOnScreen().y;
        int w = frame.getSize().width;
        int h = frame.getSize().height;

        robot.mouseMove(x + w + BORDER_SHIFT, y + h / 2);
        robot.delay(delay);
        robot.mousePress(InputEvent.BUTTON1_MASK);
        robot.delay(delay);
        for (int i = 0; i < 20; i++) {
            robot.mouseMove(x + w + i + BORDER_SHIFT, y + h / 2);
            robot.delay(50);
        }
        robot.delay(delay);
        robot.mouseRelease(InputEvent.BUTTON1_MASK);

        if (! resizeTriggered) {
            synchronized (resizeLock) {
                try {
                    resizeLock.wait(delay * 10);
                } catch (Exception e) {
                }
            }
        }

        for (int i = 0; i < components.length; i++) {
            if (! ancestorResized[i]) {
                System.err.println("FAIL: Frame resized using mouse action. " +
                                   "Ancestor resized event did not occur for " +
                                   components[i].getClass());
                passed = false;
            }
        }
        if (moveCount > 0) {
            System.err.println("FAIL: Ancestor moved event occured when Frame resized using mouse");
            passed = false;
        }

        resetValues();
        try {
            EventQueue.invokeAndWait(new Runnable() {
                public void run() {
                    frame.setLocation(frame.getLocation().x + 20, frame.getLocation().y + 20);
                    frame.invalidate();
                    frame.validate();
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
            passed = false;
        }
        if (! moveTriggered) {
            synchronized (moveLock) {
                try {
                    moveLock.wait(delay * 10);
                } catch (Exception e) {
                }
            }
        }
        for (int i = 0; i < components.length; i++) {
            if (! ancestorMoved[i]) {
                System.err.println("FAIL: Frame moved using API call. " +
                                   "Ancestor moved event did not occur for " + components[i].getClass());
                passed = false;
            }
        }
        if (resizeCount > 0) {
            System.err.println("FAIL: Ancestor resized event occured when Frame moved using API");
            passed = false;
        }
        robot.delay(delay * 10);

        resetValues();
        x = (int) frame.getLocationOnScreen().x;
        y = (int) frame.getLocationOnScreen().y;
        w = frame.getSize().width;
        h = frame.getSize().height;

        //Click on the dummy frame so that the test frame loses focus. This is to workaround
        //a bug in Linux AS.
        robot.mouseMove((int) dummy.getLocationOnScreen().x + dummy.getSize().width / 2,
                        (int) dummy.getLocationOnScreen().y + dummy.getSize().height / 2);
        robot.delay(delay);
        robot.mousePress(InputEvent.BUTTON1_MASK);
        robot.delay(delay);
        robot.mouseRelease(InputEvent.BUTTON1_MASK);
        robot.delay(delay);

        robot.mouseMove(x + w / 2, y + 10);
        robot.delay(delay);
        robot.mousePress(InputEvent.BUTTON1_MASK);
        robot.delay(delay);
        for (int i = 1; i <= 20; i++) {
            robot.mouseMove(x + w / 2 + i, y + 10);
            robot.delay(50);
        }
        robot.delay(delay);
        robot.mouseRelease(InputEvent.BUTTON1_MASK);

        if (! moveTriggered) {
            synchronized (moveLock) {
                try {
                    moveLock.wait(delay * 10);
                } catch (Exception e) {
                }
            }
        }

        for (int i = 0; i < components.length; i++) {
            if (! ancestorMoved[i]) {
                System.err.println("FAIL: Frame moved using mouse action. " +
                                   "Ancestor moved event did not occur for " + components[i].getClass());
                passed = false;
            }
        }
        if (resizeCount > 0) {
            System.err.println("FAIL: Ancestor resized event occured when Frame moved using mouse");
            passed = false;
        }

        return passed;
    }

    private void resetValues() {
        moveTriggered = false;
        resizeTriggered = false;
        moveCount = 0;
        resizeCount = 0;
        for (int i = 0; i < ancestorResized.length; i++) {
            ancestorResized[i] = false;
            ancestorMoved[i] = false;
        }
    }

    private void keyType(int key, Robot robot) throws Exception {
        robot.keyPress(key);
        robot.delay(keyDelay);
        robot.keyRelease(key);
        robot.delay(keyDelay);
    }

    class HierarchyBoundsListenerImpl implements HierarchyBoundsListener {
        // checks for Ancestor_Moved events
        public void ancestorMoved(HierarchyEvent ce) {
            if (check) {
                System.out.println("Moved " + ce.getComponent());
            }
            for (int i = 0; i < components.length; i++) {
                if (components[i].equals(ce.getComponent())) {
                    //setting this array for purpose of checking ancestor_moved.
                    ancestorMoved[i] = true;
                    moveCount++;
                    if (moveCount == components.length) {
                        moveTriggered = true;
                        synchronized (moveLock) {
                            try {
                                moveLock.notifyAll();
                            } catch (Exception e) {
                            }
                        }
                    }
                }
            }
        }
        // checks for Ancestor_Moved events
        public void ancestorResized(HierarchyEvent ce) {
            if (check) {
                System.out.println("Resized " + ce.getComponent());
            }
            for (int i = 0; i < components.length; i++) {
                if (components[i].equals(ce.getComponent())) {
                    if (! frame.equals(ce.getChanged()) || ce.getChangedParent() != null) {
                        System.err.println("FAIL: Invalid value of HierarchyEvent.getXXX");
                        System.err.println("ce.getChanged() : " + ce.getChanged());
                        System.err.println("ce.getChangedParent() : " + ce.getChangedParent());
                        passed = false;
                    }
                    //setting this array for purpose of checking ancestor_resized
                    ancestorResized[i] = true;
                    resizeCount++;
                    if (resizeCount == components.length) {
                        resizeTriggered = true;
                        synchronized (resizeLock) {
                            try {
                                resizeLock.notifyAll();
                            } catch (Exception e) {
                            }
                        }
                    }
                }
            }
        }
    }

    private Frame frame, dummy;
    private Panel panel;
    private Button button;
    private Label label;
    private List list;
    private Choice choice;
    private Checkbox checkbox;
    private Scrollbar scrollbar;
    private TextField textfield;
    private TextArea textarea;
    private Component[] components;
    private boolean[] ancestorResized;
    private boolean[] ancestorMoved;

    private int delay = 500;
    private int keyDelay = 50;
    private int moveCount = 0;
    private int resizeCount = 0;

    private boolean passed = true;
    private boolean moveTriggered = false;
    private boolean resizeTriggered = false;
    private final Object moveLock = new Object();
    private final Object resizeLock = new Object();

    private boolean check = false;

    private void invoke() throws InterruptedException {
        try {
            SwingUtilities.invokeAndWait(new Runnable() {

                public void run() {
                    prepareControls();
                }
            });
            try {
                Thread.sleep(1000); // wait for graphic effects on systems like Win7
            } catch (InterruptedException ex) {
            }
            if (!performTest()) {
                fail("Test failed");
            }
        } catch (InvocationTargetException ex) {
            fail(ex.getMessage());
        }
    }

    /*****************************************************
     * Standard Test Machinery Section
     * DO NOT modify anything in this section -- it's a
     * standard chunk of code which has all of the
     * synchronisation necessary for the test harness.
     * By keeping it the same in all tests, it is easier
     * to read and understand someone else's test, as
     * well as insuring that all tests behave correctly
     * with the test harness.
     * There is a section following this for test-
     * classes
     ******************************************************/
    private static void init() throws InterruptedException {
        //*** Create instructions for the user here ***
        //System.setProperty("sun.awt.disableMixing", "true");

        String[] instructions = {
            "This is an AUTOMATIC test, simply wait until it is done.",
            "The result (passed or failed) will be shown in the",
            "message window below."
        };
        Sysout.createDialog();
        Sysout.printInstructions(instructions);

        HierarchyBoundsListenerMixingTest instance = new HierarchyBoundsListenerMixingTest();

        instance.invoke();

        pass();
    }//End  init()
    private static boolean theTestPassed = false;
    private static boolean testGeneratedInterrupt = false;
    private static String failureMessage = "";
    private static Thread mainThread = null;
    private static int sleepTime = 300000;

    // Not sure about what happens if multiple of this test are
    //  instantiated in the same VM.  Being static (and using
    //  static vars), it aint gonna work.  Not worrying about
    //  it for now.
    public static void main(String args[]) throws InterruptedException {
        mainThread = Thread.currentThread();
        try {
            init();
        } catch (TestPassedException e) {
            //The test passed, so just return from main and harness will
            // interepret this return as a pass
            return;
        }
        //At this point, neither test pass nor test fail has been
        // called -- either would have thrown an exception and ended the
        // test, so we know we have multiple threads.

        //Test involves other threads, so sleep and wait for them to
        // called pass() or fail()
        try {
            Thread.sleep(sleepTime);
            //Timed out, so fail the test
            throw new RuntimeException("Timed out after " + sleepTime / 1000 + " seconds");
        } catch (InterruptedException e) {
            //The test harness may have interrupted the test.  If so, rethrow the exception
            // so that the harness gets it and deals with it.
            if (!testGeneratedInterrupt) {
                throw e;
            }

            //reset flag in case hit this code more than once for some reason (just safety)
            testGeneratedInterrupt = false;

            if (theTestPassed == false) {
                throw new RuntimeException(failureMessage);
            }
        }

    }//main

    public static synchronized void setTimeoutTo(int seconds) {
        sleepTime = seconds * 1000;
    }

    public static synchronized void pass() {
        Sysout.println("The test passed.");
        Sysout.println("The test is over, hit  Ctl-C to stop Java VM");
        //first check if this is executing in main thread
        if (mainThread == Thread.currentThread()) {
            //Still in the main thread, so set the flag just for kicks,
            // and throw a test passed exception which will be caught
            // and end the test.
            theTestPassed = true;
            throw new TestPassedException();
        }
        theTestPassed = true;
        testGeneratedInterrupt = true;
        mainThread.interrupt();
    }//pass()

    public static synchronized void fail() {
        //test writer didn't specify why test failed, so give generic
        fail("it just plain failed! :-)");
    }

    public static synchronized void fail(String whyFailed) {
        Sysout.println("The test failed: " + whyFailed);
        Sysout.println("The test is over, hit  Ctl-C to stop Java VM");
        //check if this called from main thread
        if (mainThread == Thread.currentThread()) {
            //If main thread, fail now 'cause not sleeping
            throw new RuntimeException(whyFailed);
        }
        theTestPassed = false;
        testGeneratedInterrupt = true;
        failureMessage = whyFailed;
        mainThread.interrupt();
    }//fail()
}// class LWComboBox
class TestPassedException extends RuntimeException {
}

//*********** End Standard Test Machinery Section **********
//************ Begin classes defined for the test ****************
// if want to make listeners, here is the recommended place for them, then instantiate
//  them in init()

/* Example of a class which may be written as part of a test
class NewClass implements anInterface
{
static int newVar = 0;

public void eventDispatched(AWTEvent e)
{
//Counting events to see if we get enough
eventCount++;

if( eventCount == 20 )
{
//got enough events, so pass

LWComboBox.pass();
}
else if( tries == 20 )
{
//tried too many times without getting enough events so fail

LWComboBox.fail();
}

}// eventDispatched()

}// NewClass class

 */
//************** End classes defined for the test *******************
/****************************************************
Standard Test Machinery
DO NOT modify anything below -- it's a standard
chunk of code whose purpose is to make user
interaction uniform, and thereby make it simpler
to read and understand someone else's test.
 ****************************************************/
/**
This is part of the standard test machinery.
It creates a dialog (with the instructions), and is the interface
for sending text messages to the user.
To print the instructions, send an array of strings to Sysout.createDialog
WithInstructions method.  Put one line of instructions per array entry.
To display a message for the tester to see, simply call Sysout.println
with the string to be displayed.
This mimics System.out.println but works within the test harness as well
as standalone.
 */
class Sysout {

    private static TestDialog dialog;

    public static void createDialogWithInstructions(String[] instructions) {
        dialog = new TestDialog(new Frame(), "Instructions");
        dialog.printInstructions(instructions);
        //dialog.setVisible(true);
        println("Any messages for the tester will display here.");
    }

    public static void createDialog() {
        dialog = new TestDialog(new Frame(), "Instructions");
        String[] defInstr = {"Instructions will appear here. ", ""};
        dialog.printInstructions(defInstr);
        //dialog.setVisible(true);
        println("Any messages for the tester will display here.");
    }

    public static void printInstructions(String[] instructions) {
        dialog.printInstructions(instructions);
    }

    public static void println(String messageIn) {
        dialog.displayMessage(messageIn);
        System.out.println(messageIn);
    }
}// Sysout  class

/**
This is part of the standard test machinery.  It provides a place for the
test instructions to be displayed, and a place for interactive messages
to the user to be displayed.
To have the test instructions displayed, see Sysout.
To have a message to the user be displayed, see Sysout.
Do not call anything in this dialog directly.
 */
class TestDialog extends Dialog {

    TextArea instructionsText;
    TextArea messageText;
    int maxStringLength = 80;

    //DO NOT call this directly, go through Sysout
    public TestDialog(Frame frame, String name) {
        super(frame, name);
        int scrollBoth = TextArea.SCROLLBARS_BOTH;
        instructionsText = new TextArea("", 15, maxStringLength, scrollBoth);
        add("North", instructionsText);

        messageText = new TextArea("", 5, maxStringLength, scrollBoth);
        add("Center", messageText);

        pack();

        //setVisible(true);
    }// TestDialog()

    //DO NOT call this directly, go through Sysout
    public void printInstructions(String[] instructions) {
        //Clear out any current instructions
        instructionsText.setText("");

        //Go down array of instruction strings

        String printStr, remainingStr;
        for (int i = 0; i < instructions.length; i++) {
            //chop up each into pieces maxSringLength long
            remainingStr = instructions[i];
            while (remainingStr.length() > 0) {
                //if longer than max then chop off first max chars to print
                if (remainingStr.length() >= maxStringLength) {
                    //Try to chop on a word boundary
                    int posOfSpace = remainingStr.lastIndexOf(' ', maxStringLength - 1);

                    if (posOfSpace <= 0) {
                        posOfSpace = maxStringLength - 1;
                    }

                    printStr = remainingStr.substring(0, posOfSpace + 1);
                    remainingStr = remainingStr.substring(posOfSpace + 1);
                } //else just print
                else {
                    printStr = remainingStr;
                    remainingStr = "";
                }

                instructionsText.append(printStr + "\n");

            }// while

        }// for

    }//printInstructions()

    //DO NOT call this directly, go through Sysout
    public void displayMessage(String messageIn) {
        messageText.append(messageIn + "\n");
        System.out.println(messageIn);
    }
}// TestDialog  class

