/*
 * Copyright (c) 2022, 2025, 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.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.awt.image.RenderedImage;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

import javax.imageio.ImageIO;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextArea;
import javax.swing.Timer;
import javax.swing.border.Border;
import javax.swing.event.HyperlinkListener;
import javax.swing.text.JTextComponent;
import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.html.StyleSheet;

import static java.util.Collections.unmodifiableList;
import static javax.swing.BorderFactory.createEmptyBorder;
import static javax.swing.SwingUtilities.invokeAndWait;
import static javax.swing.SwingUtilities.isEventDispatchThread;

/**
 * A framework for manual tests to display test instructions and
 * <i>Pass</i> / <i>Fail</i> buttons. The framework automatically
 * creates a frame to display the instructions, provides buttons
 * to select the test result, and handles test timeout.
 *
 * <p id="timeOutTimer">
 * The instruction UI frame displays a timer at the top which indicates
 * how much time is left. The timer can be paused using the <i>Pause</i>
 * button to the right of the time; the title of the button changes to
 * <i>Resume</i>. To resume the timer, use the <i>Resume</i> button.
 *
 * <p id="instructionText">
 * In the center, the instruction UI frame displays instructions for the
 * tester. The instructions can be either plain text or HTML. If the
 * text of the instructions starts with {@code "<html>"}, the
 * instructions are displayed as HTML, as supported by Swing, which
 * provides richer formatting options. To handle navigating links in the
 * instructions, call {@link Builder#hyperlinkListener} to install a listener.
 * <p>
 * The instructions are displayed in a text component with word-wrapping
 * so that there's no horizontal scroll bar. If the text doesn't fit, a
 * vertical scroll bar is shown. Use {@code rows} and {@code columns}
 * parameters to change the size of this text component.
 * If possible, choose the number of rows and columns so that
 * the instructions fit and no scroll bars are shown.
 *
 * <p id="passFailButtons">
 * At the bottom, the instruction UI frame displays the
 * <i>Pass</i> and <i>Fail</i> buttons. The tester clicks either <i>Pass</i>
 * or <i>Fail</i> button to finish the test. When the tester clicks the
 * <i>Fail</i> button, the framework displays a dialog box prompting for
 * a reason why the test fails. The tester enters the reason and clicks
 * <i>OK</i> to close the dialog and fail the test,
 * or simply closes the dialog to fail the test without providing any reason.
 *
 * <p id="screenCapture">
 * If you enable the screenshot feature, a <i>Screenshot</i> button is
 * added  to the right of the <i>Fail</i> button. The tester can choose either
 * <i>Capture Full Screen</i> (default) or <i>Capture Frames</i> and click the
 * <i>Screenshot</i> button to take a screenshot.
 * If there are multiple screens, screenshots of each screen are created.
 * If the tester selects the <i>Capture Frames</i> mode, screenshots of all
 * the windows or frames registered in the {@code PassFailJFrame} framework
 * are created.
 *
 * <p id="logArea">
 * If you enable a log area, the instruction UI frame adds a text component
 * to display log messages below the buttons.
 * Use {@link #log(String) log}, {@link #logSet(String) logSet}
 * and {@link #logClear() logClear} static methods of {@code PassFailJFrame}
 * to add or clear messages from the log area.
 *
 * <p id="awaitTestResult">
 * After you create an instance of {@code PassFailJFrame}, call the
 * {@link #awaitAndCheck() awaitAndCheck} method to stop the current thread
 * (usually the main thread) and wait until the tester clicks
 * either <i>Pass</i> or <i>Fail</i> button,
 * or until the test times out.
 * <p>
 * The call to the {@code awaitAndCheck} method is usually the last
 * statement in the {@code main} method of your test.
 * If the test fails, an exception is thrown to signal the failure to jtreg.
 * The test fails if the tester clicks the <i>Fail</i> button,
 * if the timeout occurs,
 * or if any window or frame is closed.
 * <p>
 * Before returning from {@code awaitAndCheck}, the framework disposes of
 * all the windows and frames.
 *
 * <p id="forcePassAndFail">
 * For semi-automatic tests, use {@code forcePass} or
 * {@code forceFail} methods to forcibly pass or fail the test
 * when it's determined that the required conditions are already met
 * or cannot be met correspondingly.
 * These methods release {@code awaitAndCheck}, and
 * the test will complete successfully or fail.
 * <p>
 * Refer to examples of using these methods in the description of the
 * {@link #forcePass() forcePass} and {@link #forceFail() forceFail} methods.
 *
 * <h2 id="sampleManualTest">Sample Manual Test</h2>
 * A simple test would look like this:
 * {@snippet id='sampleManualTestCode' lang='java':
 * public class SampleManualTest {
 *     private static final String INSTRUCTIONS =
 *             "Click Pass, or click Fail if the test failed.";
 *
 *     public static void main(String[] args) throws Exception {
 *         PassFailJFrame.builder()
 *                       .instructions(INSTRUCTIONS)
 *                       .testUI(SampleManualTest::createTestUI)
 *                       .build()
 *                       .awaitAndCheck();
 *     }
 *
 *     private static Window createTestUI() {
 *         JFrame testUI = new JFrame("Test UI");
 *         testUI.setSize(250, 150);
 *         return testUI;
 *     }
 * }
 * }
 * <p>
 * The above example uses the {@link Builder Builder} class to set
 * the parameters of the instruction frame.
 * It is <em>the recommended way</em>.
 *
 * <p>
 * The framework will create an instruction UI frame, it will call
 * the provided {@code createTestUI} on the Event Dispatch Thread (<dfn>EDT</dfn>),
 * and it will automatically position the test UI frame and make it visible.
 *
 * <p id="jtregTagsForTest">
 * Add the following jtreg tags before the test class declaration
 * <pre><code>
 * /*
 *  * &#64;test
 *  * @summary Sample manual test
 *  * @library /java/awt/regtesthelpers
 *  * @build PassFailJFrame
 *  * @run main/manual SampleManualTest
 *  *&#47;
 * </code></pre>
 * <p>
 * The {@code @library} tag points to the location of the
 * {@code PassFailJFrame} class in the source code;
 * the {@code @build} tag makes jtreg compile the {@code PassFailJFrame} class,
 * and finally the {@code @run} tag specifies it is a manual
 * test and the class to run.
 * <p>
 * Don't forget to update the name of the class to run in the {@code @run} tag.
 *
 * <h2 id="usingBuilder">Using {@code Builder}</h2>
 * Use methods of the {@link Builder Builder} class to set or change
 * parameters of {@code PassFailJFrame} and its instruction UI:
 * <ul>
 *     <li>{@link Builder#title(String) title} sets
 *         the title of the instruction UI
 *         (the default is {@value #TITLE});</li>
 *     <li>{@link Builder#testTimeOut(long) testTimeOut} sets
 *         the timeout of the test
 *         (the default is {@value #TEST_TIMEOUT});</li>
 *     <li>{@link Builder#rows(int) rows} and
 *         {@link Builder#columns(int) columns} control the size
 *         the text component which displays the instructions
 *         (the default number of rows is the number of lines in the text
 *         of the instructions,
 *         the default number of columns is {@value #COLUMNS});</li>
 *     <li>{@link Builder#logArea() logArea} adds a log area;</li>
 *     <li>{@link Builder#screenCapture() screenCapture}
 *         enables screenshots.</li>
 * </ul>
 *
 * <h3 id="builderTestUI">Using {@code testUI} and {@code splitUI}</h3>
 * The {@code Builder.testUI} methods accept interfaces which create one window
 * or a list of windows if the test needs multiple windows,
 * or directly a single window, an array of windows or a list of windows.
 * <p>
 * For simple test UI, use {@link Builder#splitUI(PanelCreator) splitUI},
 * or explicitly
 * {@link Builder#splitUIRight(PanelCreator) splitUIRight} or
 * {@link Builder#splitUIBottom(PanelCreator) splitUIBottom} with
 * a {@link PanelCreator PanelCreator}.
 * The framework will call the provided
 * {@code createUIPanel} method to create the component with test UI and
 * will place it as the right or bottom component in a split pane
 * along with instruction UI.
 * <p>
 * Note: <em>support for multiple windows is incomplete</em>.
 *
 * <h2 id="obsoleteSampleTest">Obsolete Sample Test</h2>
 * Alternatively, use one of the {@code PassFailJFrame} constructors to
 * create an object, then create secondary test UI, register it
 * with {@code PassFailJFrame}, position it and make it visible.
 * The following sample demonstrates it:
 * {@snippet id='obsoleteSampleTestCode' lang='java':
 * public class ObsoleteManualTest {
 *     private static final String INSTRUCTIONS =
 *             "Click Pass, or click Fail if the test failed.";
 *
 *     public static void main(String[] args) throws Exception {
 *         PassFailJFrame passFail = new PassFailJFrame(INSTRUCTIONS);
 *
 *         SwingUtilities.invokeAndWait(ObsoleteManualTest::createTestUI);
 *
 *         passFail.awaitAndCheck();
 *     }
 *
 *     private static void createTestUI() {
 *         JFrame testUI = new JFrame("Test UI");
 *         testUI.setSize(250, 150);
 *         PassFailJFrame.addTestWindow(testUI);
 *         PassFailJFrame.positionTestWindow(testUI, PassFailJFrame.Position.HORIZONTAL);
 *         testUI.setVisible(true);
 *     }
 * }
 * }
 * <p>
 * This sample uses {@link #PassFailJFrame(String) a constructor} of
 * {@code PassFailJFrame} to create its instance,
 * there are several overloads provided which allow changing other parameters.
 * <p>
 * When you use the constructors, you have to explicitly create
 * your test UI window on EDT. After you create the window,
 * you need to register it with the framework using
 * {@link #addTestWindow(Window) addTestWindow}
 * to ensure the window is disposed of when the test completes.
 * Before showing the window, you have to call
 * {@link #positionTestWindow(Window, Position) positionTestWindow}
 * to position the test window near the instruction UI frame provided
 * by the framework. And finally you have to explicitly show the test UI
 * window by calling {@code setVisible(true)}.
 * <p>
 * To avoid the complexity, use the {@link Builder Builder} class
 * which provides a streamlined way to configure and create an
 * instance of {@code PassFailJFrame}.
 * <p>
 * Consider updating tests which use {@code PassFailJFrame} constructors to
 * use the builder pattern.
 */
public final class PassFailJFrame {

    /** A default title for the instruction frame. */
    private static final String TITLE = "Test Instructions";

    /** A default test timeout. */
    private static final long TEST_TIMEOUT = 5;

    /** A default number of rows for displaying the test instructions. */
    private static final int ROWS = 10;
    /** A default number of columns for displaying the test instructions. */
    private static final int COLUMNS = 40;

    /**
     * A gap between windows.
     */
    public static final int WINDOW_GAP = 8;

    /**
     * Prefix for the user-provided failure reason.
     */
    private static final String FAILURE_REASON = "Failure Reason:\n";
    /**
     * The failure reason message when the user doesn't provide one.
     */
    private static final String EMPTY_REASON = "(no reason provided)";

    /**
     * List of windows or frames managed by the {@code PassFailJFrame}
     * framework. These windows are automatically disposed of when the
     * test is finished.
     * <p>
     * <b>Note:</b> access to this field has to be synchronized by
     * {@code PassFailJFrame.class}.
     */
    private static final List<Window> windowList = new ArrayList<>();

    private static final CountDownLatch latch = new CountDownLatch(1);

    private static TimeoutHandlerPanel timeoutHandlerPanel;

    /**
     * The description of why the test fails.
     * <p>
     * Note: <strong>do not use</strong> this field directly,
     * use the {@link #setFailureReason(String) setFailureReason} and
     * {@link #getFailureReason() getFailureReason} methods to modify and
     * to read its value.
     */
    private static String failureReason;

    private static final AtomicInteger imgCounter = new AtomicInteger(0);

    private static JFrame frame;

    private static Robot robot;

    private static JTextArea logArea;

    public enum Position {HORIZONTAL, VERTICAL, TOP_LEFT_CORNER}

    /**
     * Constructs a frame which displays test instructions and
     * the <i>Pass</i> / <i>Fail</i> buttons with the given instructions, and
     * the default timeout of {@value #TEST_TIMEOUT} minutes,
     * the default title of {@value #TITLE} and
     * the default values of {@value #ROWS} and {@value #COLUMNS}
     * for rows and columns.
     * <p>
     * See {@link #PassFailJFrame(String,String,long,int,int)} for
     * more details.
     *
     * @param instructions the instructions for the tester
     *
     * @throws InterruptedException if the current thread is interrupted
     *              while waiting for EDT to finish creating UI components
     * @throws InvocationTargetException if an exception is thrown while
     *              creating UI components on EDT
     */
    public PassFailJFrame(String instructions)
            throws InterruptedException, InvocationTargetException {
        this(instructions, TEST_TIMEOUT);
    }

    /**
     * Constructs a frame which displays test instructions and
     * the <i>Pass</i> / <i>Fail</i> buttons
     * with the given instructions and timeout as well as
     * the default title of {@value #TITLE}
     * and the default values of {@value #ROWS} and {@value #COLUMNS}
     * for rows and columns.
     * <p>
     * See {@link #PassFailJFrame(String,String,long,int,int)} for
     * more details.
     *
     * @param instructions the instructions for the tester
     * @param testTimeOut  the test timeout in minutes
     *
     * @throws InterruptedException if the current thread is interrupted
     *              while waiting for EDT to finish creating UI components
     * @throws InvocationTargetException if an exception is thrown while
     *              creating UI components on EDT
     */
    public PassFailJFrame(String instructions, long testTimeOut)
            throws InterruptedException, InvocationTargetException {
        this(TITLE, instructions, testTimeOut);
    }

    /**
     * Constructs a frame which displays test instructions and
     * the <i>Pass</i> / <i>Fail</i> buttons
     * with the given title, instructions and timeout as well as
     * the default values of {@value #ROWS} and {@value #COLUMNS}
     * for rows and columns.
     * <p>
     * See {@link #PassFailJFrame(String,String,long,int,int)} for
     * more details.
     *
     * @param title        the title of the instruction frame
     * @param instructions the instructions for the tester
     * @param testTimeOut  the test timeout in minutes
     *
     * @throws InterruptedException if the current thread is interrupted
     *              while waiting for EDT to finish creating UI components
     * @throws InvocationTargetException if an exception is thrown while
     *              creating UI components on EDT
     */
    public PassFailJFrame(String title, String instructions,
                          long testTimeOut)
            throws InterruptedException, InvocationTargetException {
        this(title, instructions, testTimeOut, ROWS, COLUMNS);
    }

    /**
     * Constructs a frame which displays test instructions and
     * the <i>Pass</i> / <i>Fail</i> buttons
     * as well as supporting UI components with the given title, instructions,
     * timeout, number of rows and columns.
     * All the UI components are created on the EDT, so it is safe to call
     * the constructor on the main thread.
     * <p>
     * After you create a test UI window, register the window using
     * {@link #addTestWindow(Window) addTestWindow} for disposal, and
     * position it close to the instruction frame using
     * {@link #positionTestWindow(Window, Position) positionTestWindow}.
     * As the last step, make your test UI window visible.
     * <p>
     * Call the {@link #awaitAndCheck() awaitAndCheck} method on the instance
     * of {@code PassFailJFrame} when you set up the testing environment.
     * <p>
     * If the tester clicks the <i>Fail</i> button, a dialog prompting for
     * a description of the problem is displayed, and then an exception
     * is thrown which fails the test.
     * If the tester clicks the <i>Pass</i> button, the test completes
     * successfully.
     * If the timeout occurs or the instruction frame is closed,
     * the test fails.
     * <p>
     * The {@code rows} and {@code columns} parameters control
     * the size of a text component which displays the instructions.
     * The preferred size of the instructions is calculated by
     * creating {@code new JTextArea(rows, columns)}.
     *
     * @param title        the title of the instruction frame
     * @param instructions the instructions for the tester
     * @param testTimeOut  the test timeout in minutes
     * @param rows         the number of rows for the text component
     *                     which displays test instructions
     * @param columns      the number of columns for the text component
     *                     which displays test instructions
     *
     * @throws InterruptedException if the current thread is interrupted
     *              while waiting for EDT to finish creating UI components
     * @throws InvocationTargetException if an exception is thrown while
     *              creating UI components on EDT
     *
     * @see JTextArea#JTextArea(int,int) JTextArea(int rows, int columns)
     * @see Builder Builder
     */
    public PassFailJFrame(String title, String instructions,
                          long testTimeOut,
                          int rows, int columns)
            throws InterruptedException, InvocationTargetException {
        invokeOnEDT(() -> createUI(title, instructions,
                                   testTimeOut,
                                   rows, columns));
    }

    /**
     * Configures {@code PassFailJFrame} using the builder.
     * It creates test UI specified using {@code testUI} or {@code splitUI}
     * methods on EDT.
     * @param builder the builder with the parameters
     * @throws InterruptedException if the current thread is interrupted while
     *              waiting for EDT to complete a task
     * @throws InvocationTargetException if an exception is thrown while
     *              running a task on EDT
     */
    private PassFailJFrame(final Builder builder)
            throws InterruptedException, InvocationTargetException {
        invokeOnEDT(() -> createUI(builder));

        if (!builder.splitUI && builder.panelCreator != null) {
            JComponent content = builder.panelCreator.createUIPanel();
            String title = content.getName();
            if (title == null) {
                title = "Test UI";
            }
            JDialog dialog = new JDialog(frame, title, false);
            dialog.addWindowListener(windowClosingHandler);
            dialog.add(content, BorderLayout.CENTER);
            dialog.pack();
            addTestWindow(dialog);
            positionTestWindow(dialog, builder.position);
        }

        if (builder.windowListCreator != null) {
            invokeOnEDT(() ->
                    builder.testWindows = builder.windowListCreator.createTestUI());
            if (builder.testWindows == null) {
                throw new IllegalStateException("Window list creator returned null list");
            }
        }

        if (builder.testWindows != null) {
            if (builder.testWindows.isEmpty()) {
                throw new IllegalStateException("Window list is empty");
            }
            addTestWindow(builder.testWindows);
            builder.testWindows
                   .forEach(w -> w.addWindowListener(windowClosingHandler));

            if (builder.positionWindows != null) {
                positionInstructionFrame(builder.position);
                invokeOnEDT(() ->
                        builder.positionWindows
                               .positionTestWindows(unmodifiableList(builder.testWindows),
                                                    builder.instructionUIHandler));
            } else {
                Window window = builder.testWindows.get(0);
                positionTestWindow(window, builder.position);
            }
        }
        showAllWindows();
    }

    /**
     * Performs an operation on EDT. If called on EDT, invokes {@code run}
     * directly, otherwise wraps into {@code invokeAndWait}.
     *
     * @param doRun an operation to run on EDT
     * @throws InterruptedException if we're interrupted while waiting for
     *              the event dispatching thread to finish executing
     *              {@code doRun.run()}
     * @throws InvocationTargetException if an exception is thrown while
     *              running {@code doRun}
     * @see javax.swing.SwingUtilities#invokeAndWait(Runnable)
     */
    private static void invokeOnEDT(Runnable doRun)
            throws InterruptedException, InvocationTargetException {
        if (isEventDispatchThread()) {
            doRun.run();
        } else {
            invokeAndWait(doRun);
        }
    }

    /**
     * Does the same as {@link #invokeOnEDT(Runnable)}, but does not throw
     * any checked exceptions.
     *
     * @param doRun an operation to run on EDT
     */
    private static void invokeOnEDTUncheckedException(Runnable doRun) {
        try {
            invokeOnEDT(doRun);
        } catch (InterruptedException | InvocationTargetException e) {
            throw new RuntimeException(e);
        }
    }

    private static void createUI(String title, String instructions,
                                 long testTimeOut, int rows, int columns) {
        frame = new JFrame(title);
        frame.setLayout(new BorderLayout());

        frame.addWindowListener(windowClosingHandler);

        frame.add(createInstructionUIPanel(instructions,
                                           testTimeOut,
                                           rows, columns,
                                           null,
                                           false,
                                           false, 0),
                  BorderLayout.CENTER);
        frame.pack();
        frame.setLocationRelativeTo(null);
        addTestWindow(frame);
    }

    private static void createUI(Builder builder) {
        frame = new JFrame(builder.title);
        frame.setLayout(new BorderLayout());

        frame.addWindowListener(windowClosingHandler);

        JComponent instructionUI =
                createInstructionUIPanel(builder.instructions,
                                         builder.testTimeOut,
                                         builder.rows, builder.columns,
                                         builder.hyperlinkListener,
                                         builder.screenCapture,
                                         builder.addLogArea,
                                         builder.logAreaRows);
        if (builder.splitUI) {
            JSplitPane splitPane = new JSplitPane(
                    builder.splitUIOrientation,
                    instructionUI,
                    builder.panelCreator.createUIPanel());
            frame.add(splitPane, BorderLayout.CENTER);
        } else {
            frame.add(instructionUI, BorderLayout.CENTER);
        }

        frame.pack();
        frame.setLocationRelativeTo(null);
        addTestWindow(frame);
    }

    private static JComponent createInstructionUIPanel(String instructions,
                                                       long testTimeOut,
                                                       int rows, int columns,
                                                       HyperlinkListener hyperlinkListener,
                                                       boolean enableScreenCapture,
                                                       boolean addLogArea,
                                                       int logAreaRows) {
        JPanel main = new JPanel(new BorderLayout());
        main.setBorder(createFrameBorder());

        timeoutHandlerPanel = new TimeoutHandlerPanel(testTimeOut);
        main.add(timeoutHandlerPanel, BorderLayout.NORTH);

        JTextComponent text = instructions.startsWith("<html>")
                              ? configureHTML(instructions, rows, columns)
                              : configurePlainText(instructions, rows, columns);
        if (hyperlinkListener != null && text instanceof JEditorPane ep) {
            ep.addHyperlinkListener(hyperlinkListener);
        }
        text.setEditable(false);
        text.setBorder(createTextBorder());
        text.setCaretPosition(0);

        JPanel textPanel = new JPanel(new BorderLayout());
        textPanel.setBorder(createEmptyBorder(GAP, 0, GAP, 0));
        textPanel.add(new JScrollPane(text), BorderLayout.CENTER);

        main.add(textPanel, BorderLayout.CENTER);

        JButton btnPass = new JButton("Pass");
        btnPass.addActionListener((e) -> {
            latch.countDown();
            timeoutHandlerPanel.stop();
        });

        JButton btnFail = new JButton("Fail");
        btnFail.addActionListener((e) -> {
            requestFailureReason();
            timeoutHandlerPanel.stop();
        });

        JPanel buttonsPanel = new JPanel(new FlowLayout(FlowLayout.CENTER,
                                                        GAP, 0));
        buttonsPanel.add(btnPass);
        buttonsPanel.add(btnFail);

        if (enableScreenCapture) {
            buttonsPanel.add(createCapturePanel());
        }

        if (addLogArea) {
            logArea = new JTextArea(logAreaRows, columns);
            logArea.setEditable(false);
            logArea.setBorder(createTextBorder());

            Box buttonsLogPanel = Box.createVerticalBox();

            buttonsLogPanel.add(buttonsPanel);
            buttonsLogPanel.add(Box.createVerticalStrut(GAP));
            buttonsLogPanel.add(new JScrollPane(logArea));

            main.add(buttonsLogPanel, BorderLayout.SOUTH);
        } else {
            main.add(buttonsPanel, BorderLayout.SOUTH);
        }

        main.setMinimumSize(main.getPreferredSize());

        return main;
    }

    private static JTextComponent configurePlainText(String instructions,
                                                     int rows, int columns) {
        JTextArea text = new JTextArea(instructions, rows, columns);
        text.setLineWrap(true);
        text.setWrapStyleWord(true);
        return text;
    }

    private static JTextComponent configureHTML(String instructions,
                                                int rows, int columns) {
        JEditorPane text = new JEditorPane("text/html", instructions);
        text.putClientProperty(JEditorPane.HONOR_DISPLAY_PROPERTIES,
                               Boolean.TRUE);
        // Set preferred size as if it were JTextArea
        text.setPreferredSize(new JTextArea(rows, columns).getPreferredSize());

        HTMLEditorKit kit = (HTMLEditorKit) text.getEditorKit();
        StyleSheet styles = kit.getStyleSheet();
        // Reduce the list default margins
        styles.addRule("ol, ul { margin-left-ltr: 30; margin-left-rtl: 30 }");
        // Make the size of code (and other elements) the same as other text
        styles.addRule("code, kbd, samp, pre { font-size: inherit; background: #DDD; }");

        return text;
    }

    /** A default gap between components. */
    private static final int GAP = 4;

    /**
     * Creates a default border for frames or dialogs.
     * It uses the default gap of {@value GAP}.
     *
     * @return the border for frames and dialogs
     */
    private static Border createFrameBorder() {
        return createEmptyBorder(GAP, GAP, GAP, GAP);
    }

    /**
     * Creates a border set to text area.
     * It uses the default gap of {@value GAP}.
     *
     * @return the border for text area
     */
    private static Border createTextBorder() {
        return createEmptyBorder(GAP, GAP, GAP, GAP);
    }


    /**
     * Creates a test UI window.
     */
    @FunctionalInterface
    public interface WindowCreator {
        /**
         * Creates a window for test UI.
         * This method is called by the framework on the EDT.
         * @return a test UI window
         */
        Window createTestUI();
    }

    /**
     * Creates a list of test UI windows.
     */
    @FunctionalInterface
    public interface WindowListCreator {
        /**
         * Creates one or more windows for test UI.
         * This method is called by the framework on the EDT.
         * @return a list of test UI windows
         */
        List<? extends Window> createTestUI();
    }

    /**
     * Creates a component (panel) with test UI
     * to be hosted in a split pane or a frame.
     */
    @FunctionalInterface
    public interface PanelCreator {
        /**
         * Creates a component which hosts test UI. This component
         * is placed into a split pane or into a frame to display the UI.
         * <p>
         * This method is called by the framework on the EDT.
         * @return a component (panel) with test UI
         */
        JComponent createUIPanel();
    }

    /**
     * Positions test UI windows.
     */
    @FunctionalInterface
    public interface PositionWindows {
        /**
         * Positions test UI windows.
         * This method is called by the framework on the EDT after
         * the instruction UI frame was positioned on the screen.
         * <p>
         * The list of the test windows contains the windows
         * that were passed to the framework via the
         * {@link Builder#testUI(Window...) testUI(Window...)} method or
         * that were created with {@code WindowCreator}
         * or {@code WindowListCreator} which were passed via
         * {@link Builder#testUI(WindowCreator) testUI(WindowCreator)} or
         * {@link Builder#testUI(WindowListCreator) testUI(WindowListCreator)}
         * correspondingly.
         *
         * @param testWindows the list of test windows
         * @param instructionUI information about the instruction frame
         */
        void positionTestWindows(List<Window> testWindows,
                                 InstructionUI instructionUI);
    }

    /**
     * Provides information about the instruction frame.
     */
    public interface InstructionUI {
        /**
         * {@return the location of the instruction frame}
         */
        Point getLocation();

        /**
         * {@return the size of the instruction frame}
         */
        Dimension getSize();

        /**
         * {@return the bounds of the instruction frame}
         */
        Rectangle getBounds();

        /**
         * Allows to change the location of the instruction frame.
         *
         * @param location the new location of the instruction frame
         */
        void setLocation(Point location);

        /**
         * Allows to change the location of the instruction frame.
         *
         * @param x the <i>x</i> coordinate of the new location
         * @param y the <i>y</i> coordinate of the new location
         */
        void setLocation(int x, int y);

        /**
         * Returns the specified position that was used to set
         * the initial location of the instruction frame.
         *
         * @return the specified position
         *
         * @see Position
         */
        Position getPosition();
    }


    private static final class TimeoutHandlerPanel
            extends JPanel
            implements ActionListener {

        private static final String PAUSE_BUTTON_LABEL = "Pause";
        private static final String RESUME_BUTTON_LABEL = "Resume";

        private long endTime;
        private long pauseTimeLeft;

        private final Timer timer;

        private final JLabel label;
        private final JButton button;

        public TimeoutHandlerPanel(final long testTimeOut) {
            endTime = System.currentTimeMillis()
                    + TimeUnit.MINUTES.toMillis(testTimeOut);

            label =  new JLabel("", JLabel.CENTER);
            button = new JButton(PAUSE_BUTTON_LABEL);

            button.setFocusPainted(false);
            button.setFont(new Font(Font.DIALOG, Font.BOLD, 10));
            button.addActionListener(e -> pauseToggle());

            setLayout(new BorderLayout());
            add(label, BorderLayout.CENTER);
            add(button, BorderLayout.EAST);

            timer = new Timer(1000, this);
            timer.start();
            updateTime(testTimeOut);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            long leftTime = endTime - System.currentTimeMillis();
            if (leftTime < 0) {
                timer.stop();
                setFailureReason(FAILURE_REASON
                                 + "Timeout - User did not perform testing.");
                latch.countDown();
            }
            updateTime(leftTime);
        }

        private void updateTime(final long leftTime) {
            if (leftTime < 0) {
                label.setText("Test timeout: 00:00:00");
                return;
            }
            long hours = leftTime / 3_600_000;
            long minutes = (leftTime - hours * 3_600_000) / 60_000;
            long seconds = (leftTime - hours * 3_600_000 - minutes * 60_000) / 1_000;
            label.setText(String.format(Locale.ENGLISH,
                                        "Test timeout: %02d:%02d:%02d",
                                        hours, minutes, seconds));
        }


        private void pauseToggle() {
            if (timer.isRunning()) {
                pauseTimeLeft = endTime - System.currentTimeMillis();
                timer.stop();
                label.setEnabled(false);
                button.setText(RESUME_BUTTON_LABEL);
            } else {
                endTime = System.currentTimeMillis() + pauseTimeLeft;
                updateTime(pauseTimeLeft);
                timer.start();
                label.setEnabled(true);
                button.setText(PAUSE_BUTTON_LABEL);
            }
        }

        public void stop() {
            timer.stop();
        }
    }


    private static final class WindowClosingHandler extends WindowAdapter {
        @Override
        public void windowClosing(WindowEvent e) {
            setFailureReason(FAILURE_REASON
                             + "User closed a window");
            latch.countDown();
        }
    }

    private static final WindowListener windowClosingHandler =
            new WindowClosingHandler();


    private static JComponent createCapturePanel() {
        JComboBox<CaptureType> screenShortType = new JComboBox<>(CaptureType.values());

        JButton capture = new JButton("Screenshot");
        capture.addActionListener((e) ->
                captureScreen((CaptureType) screenShortType.getSelectedItem()));

        JPanel panel = new JPanel();
        panel.add(screenShortType);
        panel.add(capture);
        return panel;
    }

    private enum CaptureType {
        FULL_SCREEN("Capture Full Screen"),
        WINDOWS("Capture Frames");

        private final String type;
        CaptureType(String type) {
            this.type = type;
        }

        @Override
        public String toString() {
            return type;
        }
    }

    private static Robot createRobot() {
        if (robot == null) {
            try {
                robot = new Robot();
            } catch (AWTException e) {
                String errorMsg = "Failed to create an instance of Robot.";
                JOptionPane.showMessageDialog(frame, errorMsg, "Failed",
                                              JOptionPane.ERROR_MESSAGE);
                forceFail(errorMsg + e.getMessage());
            }
        }
        return robot;
    }

    private static void captureScreen(Rectangle bounds) {
        Robot robot = createRobot();

        List<Image> imageList = robot.createMultiResolutionScreenCapture(bounds)
                                     .getResolutionVariants();
        Image image = imageList.get(imageList.size() - 1);

        File file = new File("CaptureScreen_"
                             + imgCounter.incrementAndGet() + ".png");
        try {
            ImageIO.write((RenderedImage) image, "png", file);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    private static void captureScreen(CaptureType type) {
        switch (type) {
            case FULL_SCREEN:
                Arrays.stream(GraphicsEnvironment.getLocalGraphicsEnvironment()
                                                 .getScreenDevices())
                      .map(GraphicsDevice::getDefaultConfiguration)
                      .map(GraphicsConfiguration::getBounds)
                      .forEach(PassFailJFrame::captureScreen);
                break;

            case WINDOWS:
                synchronized (PassFailJFrame.class) {
                    windowList.stream()
                              .filter(Window::isShowing)
                              .map(Window::getBounds)
                              .forEach(PassFailJFrame::captureScreen);
                }
                break;

            default:
                throw new IllegalStateException("Unexpected value of capture type");
        }

        JOptionPane.showMessageDialog(frame,
                                      "Screen Captured Successfully",
                                      "Screen Capture",
                                      JOptionPane.INFORMATION_MESSAGE);
    }

    /**
     * Sets the failure reason which describes why the test fails.
     * This method ensures the {@code failureReason} field does not change
     * after it's set to a non-{@code null} value.
     * @param reason the description of why the test fails
     * @throws IllegalArgumentException if the {@code reason} parameter
     *         is {@code null}
     */
    private static synchronized void setFailureReason(final String reason) {
        if (reason == null) {
            throw new IllegalArgumentException("The failure reason must not be null");
        }
        if (failureReason == null) {
            failureReason = reason;
        }
    }

    /**
     * {@return the description of why the test fails}
     */
    private static synchronized String getFailureReason() {
        return failureReason;
    }

    /**
     * Wait for the user decision i,e user selects pass or fail button.
     * If user does not select pass or fail button then the test waits for
     * the specified timeoutMinutes period and the test gets timeout.
     * Note: This method should be called from main() thread
     *
     * @throws InterruptedException      exception thrown when thread is
     *                                   interrupted
     * @throws InvocationTargetException if an exception is thrown while
     *                                   disposing of frames on EDT
     */
    public void awaitAndCheck() throws InterruptedException, InvocationTargetException {
        if (isEventDispatchThread()) {
            throw new IllegalStateException("awaitAndCheck() should not be called on EDT");
        }
        latch.await();
        invokeAndWait(PassFailJFrame::disposeWindows);

        String failure = getFailureReason();
        if (failure != null) {
            throw new RuntimeException(failure);
        }

        System.out.println("Test passed!");
    }

    /**
     * Requests the description of the test failure reason from the tester.
     */
    private static void requestFailureReason() {
        final JDialog dialog = new JDialog(frame, "Failure reason", true);

        JTextArea reason = new JTextArea(5, 20);
        reason.setBorder(createTextBorder());

        JButton okButton = new JButton("OK");
        okButton.addActionListener((ae) -> {
            String text = reason.getText();
            setFailureReason(FAILURE_REASON
                             + (!text.isEmpty() ? text : EMPTY_REASON));
            dialog.setVisible(false);
        });

        JPanel okayBtnPanel = new JPanel(new FlowLayout(FlowLayout.CENTER,
                                                        GAP, 0));
        okayBtnPanel.setBorder(createEmptyBorder(GAP, 0, 0, 0));
        okayBtnPanel.add(okButton);

        JPanel main = new JPanel(new BorderLayout());
        main.setBorder(createFrameBorder());
        main.add(new JScrollPane(reason), BorderLayout.CENTER);
        main.add(okayBtnPanel, BorderLayout.SOUTH);

        dialog.add(main);
        dialog.setLocationRelativeTo(frame);
        dialog.pack();
        dialog.setVisible(true);

        // Ensure the test fails even if the dialog is closed
        // without clicking the OK button
        setFailureReason(FAILURE_REASON + EMPTY_REASON);

        dialog.dispose();
        latch.countDown();
    }

    /**
     * Disposes of all the windows. It disposes of the test instruction frame
     * and all other windows added via {@link #addTestWindow(Window)}.
     */
    private static synchronized void disposeWindows() {
        windowList.forEach(Window::dispose);
    }

    private static void positionInstructionFrame(final Position position) {
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();

        // Get the screen insets to position the frame by taking into
        // account the location of taskbar or menu bar on screen.
        GraphicsConfiguration gc = GraphicsEnvironment.getLocalGraphicsEnvironment()
                                                      .getDefaultScreenDevice()
                                                      .getDefaultConfiguration();
        Insets screenInsets = Toolkit.getDefaultToolkit().getScreenInsets(gc);

        switch (position) {
            case HORIZONTAL:
                int newX = (((screenSize.width + WINDOW_GAP) / 2) - frame.getWidth());
                frame.setLocation((newX + screenInsets.left),
                                  (frame.getY() + screenInsets.top));
                break;

            case VERTICAL:
                int newY = (((screenSize.height + WINDOW_GAP) / 2) - frame.getHeight());
                frame.setLocation((frame.getX() + screenInsets.left),
                                  (newY + screenInsets.top));
                break;

            case TOP_LEFT_CORNER:
                frame.setLocation(screenInsets.left, screenInsets.top);
                break;
        }
        syncLocationToWindowManager();
    }

    /**
     * Approximately positions the instruction frame relative to the test
     * window as specified by the {@code position} parameter. If {@code testWindow}
     * is {@code null}, only the instruction frame is positioned according to
     * {@code position} parameter.
     * <p>This method should be called before making the test window visible
     * to avoid flickering.</p>
     *
     * @param testWindow test window that the test created.
     *                   May be {@code null}.
     *
     * @param position  position must be one of:
     *                  <ul>
     *                  <li>{@code HORIZONTAL} - the test instruction frame is positioned
     *                  such that its right edge aligns with screen's horizontal center
     *                  and the test window (if not {@code null}) is placed to the right
     *                  of the instruction frame.</li>
     *
     *                  <li>{@code VERTICAL} - the test instruction frame is positioned
     *                  such that its bottom edge aligns with the screen's vertical center
     *                  and the test window (if not {@code null}) is placed below the
     *                  instruction frame.</li>
     *
     *                  <li>{@code TOP_LEFT_CORNER} - the test instruction frame is positioned
     *                  such that its top left corner is at the top left corner of the screen
     *                  and the test window (if not {@code null}) is placed to the right of
     *                  the instruction frame.</li>
     *                  </ul>
     */
    public static void positionTestWindow(Window testWindow, Position position) {
        positionInstructionFrame(position);

        if (testWindow != null) {
            switch (position) {
                case HORIZONTAL:
                case TOP_LEFT_CORNER:
                    testWindow.setLocation((frame.getX() + frame.getWidth() + WINDOW_GAP),
                                           frame.getY());
                    break;

                case VERTICAL:
                    testWindow.setLocation(frame.getX(),
                                           (frame.getY() + frame.getHeight() + WINDOW_GAP));
                    break;
            }
        }

        // make instruction frame visible after updating
        // frame & window positions
        frame.setVisible(true);
    }

    /**
     * Ensures the frame location is updated by the window manager
     * if it adjusts the frame location after {@code setLocation}.
     *
     * @see #positionTestWindow
     */
    private static void syncLocationToWindowManager() {
        Toolkit.getDefaultToolkit().sync();
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     * Returns the current position and size of the test instruction frame.
     * This method can be used in scenarios when custom positioning of
     * multiple test windows w.r.t test instruction frame is necessary,
     * at test-case level and the desired configuration is not available
     * as a {@code Position} option.
     *
     * @return Rectangle bounds of test instruction frame
     * @see #positionTestWindow
     *
     * @throws InterruptedException      exception thrown when thread is
     *                                   interrupted
     * @throws InvocationTargetException if an exception is thrown while
     *                                   obtaining frame bounds on EDT
     */
    public static Rectangle getInstructionFrameBounds()
            throws InterruptedException, InvocationTargetException {
        final Rectangle[] bounds = {null};

        invokeOnEDT(() -> bounds[0] = frame != null ? frame.getBounds() : null);
        return bounds[0];
    }

    /**
     * Add the testWindow to the windowList so that test instruction frame
     * and testWindow and any other windows used in this test is disposed
     * via disposeWindows().
     *
     * @param testWindow testWindow that needs to be disposed
     */
    public static synchronized void addTestWindow(Window testWindow) {
        windowList.add(testWindow);
    }

    /**
     * Adds a collection of test windows to the windowList to be disposed of
     * when the test completes.
     *
     * @param testWindows the collection of test windows to be disposed of
     */
    public static synchronized void addTestWindow(Collection<? extends Window> testWindows) {
        windowList.addAll(testWindows);
    }

    /**
     * Displays all the windows in {@code windowList}.
     *
     * @throws InterruptedException if the thread is interrupted while
     *              waiting for the event dispatch thread to finish running
     *              the {@link #showUI() showUI}
     * @throws InvocationTargetException if an exception is thrown while
     *              the event dispatch thread executes {@code showUI}
     */
    private static void showAllWindows()
            throws InterruptedException, InvocationTargetException {
        invokeOnEDT(PassFailJFrame::showUI);
    }

    /**
     * Displays all the windows in {@code windowList}; it has to be called on
     * the EDT &mdash; use {@link #showAllWindows() showAllWindows} to ensure it.
     */
    private static synchronized void showUI() {
        windowList.forEach(w -> w.setVisible(true));
    }


    /**
     * Forcibly pass the test.
     * <p>
     * Use this method in semi-automatic tests when
     * the test determines that all the conditions for passing the test are met.
     * <p>
     * <strong>Do not use</strong> this method in cases where a resource is unavailable or a
     * feature isn't supported, throw {@code jtreg.SkippedException} instead.
     *
     * <p>A sample usage can be found in
     * <a href="https://github.com/openjdk/jdk/blob/7283c8b/test/jdk/java/awt/FileDialog/SaveFileNameOverrideTest.java#L84">{@code
     * SaveFileNameOverrideTest.java}</a>
     */
    public static void forcePass() {
        latch.countDown();
    }

    /**
     * Forcibly fail the test.
     * <p>
     * Use this method in semi-automatic tests when
     * it is determined that the conditions for passing the test cannot be met.
     * <p>
     * <strong>Do not use</strong> this method in cases where a resource is unavailable or a
     * feature isn't supported, throw {@code jtreg.SkippedException} instead.
     *
     * <p>A sample usage can be found in
     * <a href="https://github.com/openjdk/jdk/blob/0844745e7bd954a96441365f8010741ec1c29dbf/test/jdk/javax/swing/JScrollPane/AcceleratedWheelScrolling/HorizScrollers.java#L180">{@code
     * HorizScrollers.java}</a>
     */
    public static void forceFail() {
        forceFail("forceFail called");
    }

    /**
     * Forcibly fail the test and provide a reason.
     * <p>
     * Use this method in semi-automatic tests when
     * it is determined that the conditions for passing the test cannot be met.
     * <p>
     * <strong>Do not use</strong> this method in cases where a resource is unavailable or a
     * feature isn't supported, throw {@code jtreg.SkippedException} instead.
     *
     * <p>A sample usage can be found in
     * <a href="https://github.com/openjdk/jdk/blob/7283c8b075aa289dbb9cb80f6937b3349c8d4769/test/jdk/java/awt/FileDialog/SaveFileNameOverrideTest.java#L86">{@code
     * SaveFileNameOverrideTest.java}</a>
     *
     * @param reason the reason why the test is failed
     */
    public static void forceFail(String reason) {
        setFailureReason(FAILURE_REASON + reason);
        latch.countDown();
    }

    /**
     * Adds a {@code message} to the log area, if enabled by
     * {@link Builder#logArea() logArea()} or
     * {@link Builder#logArea(int) logArea(int)}.
     *
     * @param message the message to log
     */
    public static void log(String message) {
        System.out.println("PassFailJFrame: " + message);
        invokeOnEDTUncheckedException(() -> logArea.append(message + "\n"));
    }

    /**
     * Clears the log area, if enabled by
     * {@link Builder#logArea() logArea()} or
     * {@link Builder#logArea(int) logArea(int)}.
     */
    public static void logClear() {
        System.out.println("\nPassFailJFrame: log cleared\n");
        invokeOnEDTUncheckedException(() -> logArea.setText(""));
    }

    /**
     * Replaces the log area content with provided {@code text}, if enabled by
     * {@link Builder#logArea() logArea()} or
     * {@link Builder#logArea(int) logArea(int)}.
     *
     * @param text new text for the log area
     */
    public static void logSet(String text) {
        System.out.println("\nPassFailJFrame: log set to:\n" + text + "\n");
        invokeOnEDTUncheckedException(() -> logArea.setText(text));
    }

    public static final class Builder {
        private String title;
        private String instructions;
        private long testTimeOut;
        private int rows;
        private int columns;
        private boolean screenCapture;
        private HyperlinkListener hyperlinkListener;
        private boolean addLogArea;
        private int logAreaRows = 10;

        private List<? extends Window> testWindows;
        private WindowListCreator windowListCreator;
        private PanelCreator panelCreator;
        private boolean splitUI;
        private int splitUIOrientation;
        private PositionWindows positionWindows;
        private InstructionUI instructionUIHandler;

        private Position position;

        /**
         * A private constructor for the builder,
         * it should not be created directly.
         * Use {@code PassFailJFrame.builder()} method instead.
         */
        private Builder() {
        }

        public Builder title(String title) {
            this.title = title;
            return this;
        }

        public Builder instructions(String instructions) {
            this.instructions = instructions;
            return this;
        }

        public Builder testTimeOut(long testTimeOut) {
            this.testTimeOut = testTimeOut;
            return this;
        }

        /**
         * Sets the number of rows for displaying the instruction text.
         * The default value is the number of lines in the text plus 1:
         * {@code ((int) instructions.lines().count() + 1)}.
         *
         * @param rows the number of rows for instruction text
         * @return this builder
         */
        public Builder rows(int rows) {
            this.rows = rows;
            return this;
        }

        private int getDefaultRows() {
            return (int) instructions.lines().count() + 1;
        }

        /**
         * Adds a certain number of rows for displaying the instruction text.
         *
         * @param rowsAdd the number of rows to add to the number of rows
         * @return this builder
         * @see #rows
         */
        public Builder rowsAdd(int rowsAdd) {
            if (rows == 0) {
                rows = getDefaultRows();
            }
            rows += rowsAdd;

            return this;
        }

        /**
         * Sets the number of columns for displaying the instruction text.
         *
         * @param columns the number of columns for instruction text
         * @return this builder
         */
        public Builder columns(int columns) {
            this.columns = columns;
            return this;
        }

        /**
         * Sets a {@link HyperlinkListener} for navigating links inside
         * the instructions pane.
         *
         * @param hyperlinkListener the listener
         * @return this builder
         */
        public Builder hyperlinkListener(HyperlinkListener hyperlinkListener) {
            this.hyperlinkListener = hyperlinkListener;
            return this;
        }

        public Builder screenCapture() {
            this.screenCapture = true;
            return this;
        }

        /**
         * Adds a log area below the "Pass", "Fail" buttons.
         * <p>
         * The log area can be controlled by {@link #log(String)},
         * {@link #logClear()} and {@link #logSet(String)}.
         *
         * @return this builder
         */
        public Builder logArea() {
            this.addLogArea = true;
            return this;
        }

        /**
         * Adds a log area below the "Pass", "Fail" buttons.
         * <p>
         * The log area can be controlled by {@link #log(String)},
         * {@link #logClear()} and {@link #logSet(String)}.
         * <p>
         * The number of columns is taken from the number of
         * columns in the instructional JTextArea.
         *
         * @param rows of the log area
         * @return this builder
         */
        public Builder logArea(int rows) {
            this.addLogArea = true;
            this.logAreaRows = rows;
            return this;
        }

        /**
         * Adds a {@code WindowCreator} which the framework will use
         * to create the test UI window.
         *
         * @param windowCreator a {@code WindowCreator}
         *              to create the test UI window
         * @return this builder
         * @throws IllegalArgumentException if {@code windowCreator} is {@code null}
         * @throws IllegalStateException if a window creator
         *              or a list of test windows is already set
         */
        public Builder testUI(WindowCreator windowCreator) {
            if (windowCreator == null) {
                throw new IllegalArgumentException("The window creator can't be null");
            }

            checkWindowsLists();

            this.windowListCreator = () -> List.of(windowCreator.createTestUI());
            return this;
        }


        /**
         * Adds an implementation of {@link PositionWindows PositionWindows}
         * which the framework will use to position multiple test UI windows.
         *
         * @param positionWindows an implementation of {@code PositionWindows}
         *                        to position multiple test UI windows
         * @return this builder
         * @throws IllegalArgumentException if the {@code positionWindows}
         *              parameter is {@code null}
         * @throws IllegalStateException if the {@code positionWindows} field
         *              is already set
         */
        public Builder positionTestUI(PositionWindows positionWindows) {
            if (positionWindows == null) {
                throw new IllegalArgumentException("positionWindows parameter can't be null");
            }
            if (this.positionWindows != null) {
                throw new IllegalStateException("PositionWindows is already set");
            }
            this.positionWindows = positionWindows;
            return this;
        }

        /**
         * Positions the test UI windows in a row to the right of
         * the instruction frame. The top of the windows is aligned to
         * that of the instruction frame.
         *
         * @return this builder
         */
        public Builder positionTestUIRightRow() {
            return position(Position.HORIZONTAL)
                   .positionTestUI(WindowLayouts::rightOneRow);
        }

        /**
         * Positions the test UI windows in a column to the right of
         * the instruction frame. The top of the first window is aligned to
         * that of the instruction frame.
         *
         * @return this builder
         */
        public Builder positionTestUIRightColumn() {
            return position(Position.HORIZONTAL)
                   .positionTestUI(WindowLayouts::rightOneColumn);
        }

        /**
         * Positions the test UI windows in a column to the right of
         * the instruction frame centering the stack of the windows.
         *
         * @return this builder
         */
        public Builder positionTestUIRightColumnCentered() {
            return position(Position.HORIZONTAL)
                   .positionTestUI(WindowLayouts::rightOneColumnCentered);
        }

        /**
         * Positions the test UI windows in a row to the bottom of
         * the instruction frame. The left of the first window is aligned to
         * that of the instruction frame.
         *
         * @return this builder
         */
        public Builder positionTestUIBottomRow() {
            return position(Position.VERTICAL)
                   .positionTestUI(WindowLayouts::bottomOneRow);
        }

        /**
         * Positions the test UI windows in a row to the bottom of
         * the instruction frame centering the row of the windows.
         *
         * @return this builder
         */
        public Builder positionTestUIBottomRowCentered() {
            return position(Position.VERTICAL)
                   .positionTestUI(WindowLayouts::bottomOneRowCentered);
        }

        /**
         * Positions the test UI windows in a column to the bottom of
         * the instruction frame. The left of the first window is aligned to
         * that of the instruction frame.
         *
         * @return this builder
         */
        public Builder positionTestUIBottomColumn() {
            return position(Position.VERTICAL)
                   .positionTestUI(WindowLayouts::bottomOneColumn);
        }


        /**
         * Adds a {@code WindowListCreator} which the framework will use
         * to create a list of test UI windows.
         *
         * @param windowListCreator a {@code WindowListCreator}
         *              to create test UI windows
         * @return this builder
         * @throws IllegalArgumentException if {@code windowListCreator} is {@code null}
         * @throws IllegalStateException if a window creator
         *              or a list of test windows is already set
         */
        public Builder testUI(WindowListCreator windowListCreator) {
            if (windowListCreator == null) {
                throw new IllegalArgumentException("The window list creator can't be null");
            }

            checkWindowsLists();

            this.windowListCreator = windowListCreator;
            return this;
        }

        /**
         * Adds an already created test UI window.
         * The window is positioned and shown automatically.
         *
         * @param window a test UI window
         * @return this builder
         */
        public Builder testUI(Window window) {
            return testUI(List.of(window));
        }

        /**
         * Adds an array of already created test UI windows.
         *
         * @param windows an array of test UI windows
         * @return this builder
         */
        public Builder testUI(Window... windows) {
            return testUI(List.of(windows));
        }

        /**
         * Adds a list of already created test UI windows.
         *
         * @param windows a list of test UI windows
         * @return this builder
         * @throws IllegalArgumentException if {@code windows} is {@code null}
         *              or the list contains {@code null}
         * @throws IllegalStateException if a window creator
         *              or a list of test windows is already set
         */
        public Builder testUI(List<? extends Window> windows) {
            if (windows == null) {
                throw new IllegalArgumentException("The list of windows can't be null");
            }
            if (windows.stream()
                       .anyMatch(Objects::isNull)) {
                throw new IllegalArgumentException("The list of windows can't contain null");
            }

            checkWindowsLists();

            this.testWindows = windows;
            return this;
        }

        /**
         * Verifies the state of window list and window creator.
         *
         * @throws IllegalStateException if a windows list creator
         *              or a list of test windows is already set
         */
        private void checkWindowsLists() {
            if (windowListCreator != null) {
                throw new IllegalStateException("Window list creator is already set");
            }
            if (testWindows != null) {
                throw new IllegalStateException("The list of test windows is already set");
            }
        }

        /**
         * Adds a {@code PanelCreator} which the framework will use
         * to create a component and place it into a dialog.
         *
         * @param panelCreator a {@code PanelCreator} to create a component
         *                     with test UI
         * @return this builder
         * @throws IllegalStateException if split UI was enabled using
         *              a {@code splitUI} method
         */
        public Builder testUI(PanelCreator panelCreator) {
            if (splitUI) {
                throw new IllegalStateException("Can't combine splitUI and "
                                                + "testUI with panelCreator");
            }
            this.panelCreator = panelCreator;
            return this;
        }


        /**
         * Adds a {@code PanelCreator} which the framework will use
         * to create a component with test UI and display it in a split pane.
         * <p>
         * By default, horizontal orientation is used,
         * and test UI is displayed to the right of the instruction UI.
         *
         * @param panelCreator a {@code PanelCreator} to create a component
         *                     with test UI
         * @return this builder
         *
         * @throws IllegalStateException if a {@code PanelCreator} is
         *              already set
         * @throws IllegalArgumentException if {@code panelCreator} is {@code null}
         */
        public Builder splitUI(PanelCreator panelCreator) {
            return splitUIRight(panelCreator);
        }

        /**
         * Adds a {@code PanelCreator} which the framework will use
         * to create a component with test UI and display it
         * to the right of instruction UI.
         *
         * @param panelCreator a {@code PanelCreator} to create a component
         *                     with test UI
         * @return this builder
         *
         * @throws IllegalStateException if a {@code PanelCreator} is
         *              already set
         * @throws IllegalArgumentException if {@code panelCreator} is {@code null}
         */
        public Builder splitUIRight(PanelCreator panelCreator) {
            return splitUI(panelCreator, JSplitPane.HORIZONTAL_SPLIT);
        }

        /**
         * Adds a {@code PanelCreator} which the framework will use
         * to create a component with test UI and display it
         * in the bottom of instruction UI.
         *
         * @param panelCreator a {@code PanelCreator} to create a component
         *                     with test UI
         * @return this builder
         *
         * @throws IllegalStateException if a {@code PanelCreator} is
         *              already set
         * @throws IllegalArgumentException if {@code panelCreator} is {@code null}
         */
        public Builder splitUIBottom(PanelCreator panelCreator) {
            return splitUI(panelCreator, JSplitPane.VERTICAL_SPLIT);
        }

        /**
         * Enables split UI and stores the orientation of the split pane.
         *
         * @param panelCreator a {@code PanelCreator} to create a component
         *                     with test UI
         * @param splitUIOrientation orientation of the split pane
         * @return this builder
         *
         * @throws IllegalStateException if a {@code PanelCreator} is
         *              already set
         * @throws IllegalArgumentException if {@code panelCreator} is {@code null}
         */
        private Builder splitUI(PanelCreator panelCreator,
                                int splitUIOrientation) {
            if (panelCreator == null) {
                throw new IllegalArgumentException("A PanelCreator cannot be null");
            }
            if (this.panelCreator != null) {
                throw new IllegalStateException("A PanelCreator is already set");
            }

            splitUI = true;
            this.splitUIOrientation = splitUIOrientation;
            this.panelCreator = panelCreator;
            return this;
        }

        public Builder position(Position position) {
            this.position = position;
            return this;
        }

        public PassFailJFrame build() throws InterruptedException,
                InvocationTargetException {
            try {
                validate();
                return new PassFailJFrame(this);
            } catch (final Throwable t) {
                // Dispose of all the windows, including those that may not
                // be registered with PassFailJFrame to allow AWT to shut down
                try {
                    invokeOnEDT(() -> Arrays.stream(Window.getWindows())
                                            .forEach(Window::dispose));
                } catch (Throwable edt) {
                    t.addSuppressed(edt);
                }
                throw t;
            }
        }

        /**
         * Returns the file name of the test, if the {@code test.file} property
         * is defined, concatenated with {@code " - "} which serves as a prefix
         * to the default instruction frame title;
         * or an empty string if the {@code test.file} property is not defined.
         *
         * @return the prefix to the default title:
         *         either the file name of the test or an empty string
         *
         * @see <a href="https://openjdk.org/jtreg/tag-spec.html#testvars">jtreg
         * test-specific system properties and environment variables</a>
         */
        private static String getTestFileNamePrefix() {
            String testFile = System.getProperty("test.file");
            if (testFile == null) {
                return "";
            }

            return Paths.get(testFile).getFileName().toString()
                   + " - ";
        }

        /**
         * Validates the state of the builder and
         * expands parameters that have no assigned values
         * to their default values.
         *
         * @throws IllegalStateException if no instructions are provided,
         *              or if {@code PositionWindows} implementation is
         *              provided but neither window creator nor
         *              test window list are set
         */
        private void validate() {
            if (title == null) {
                title = getTestFileNamePrefix() + TITLE;
            }

            if (instructions == null || instructions.isEmpty()) {
                throw new IllegalStateException("Please provide the test " +
                        "instructions for this manual test");
            }

            if (testTimeOut == 0L) {
                testTimeOut = TEST_TIMEOUT;
            }

            if (rows == 0) {
                rows = getDefaultRows();
            }

            if (columns == 0) {
                columns = COLUMNS;
            }

            if (position == null
                && (testWindows != null || windowListCreator != null
                    || (!splitUI && panelCreator != null))) {

                position = Position.HORIZONTAL;
            }

            if (positionWindows != null) {
                if (testWindows == null && windowListCreator == null) {
                    throw new IllegalStateException("To position windows, "
                            + "provide a list of windows to the builder");
                }
                instructionUIHandler = new InstructionUIHandler();
            }
        }

        private final class InstructionUIHandler implements InstructionUI {
            @Override
            public Point getLocation() {
                return frame.getLocation();
            }

            @Override
            public Dimension getSize() {
                return frame.getSize();
            }

            @Override
            public Rectangle getBounds() {
                return frame.getBounds();
            }

            @Override
            public void setLocation(Point location) {
                setLocation(location.x, location.y);
            }

            @Override
            public void setLocation(int x, int y) {
                frame.setLocation(x, y);
            }

            @Override
            public Position getPosition() {
                return position;
            }
        }
    }

    /**
     * Creates a builder for configuring {@code PassFailJFrame}.
     *
     * @return the builder for configuring {@code PassFailJFrame}
     */
    public static Builder builder() {
        return new Builder();
    }
}
