/*
 * Copyright 2014 JBoss Inc
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.optaplanner.benchmark.impl.aggregator.swingui;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;
import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.ScrollPaneConstants;
import javax.swing.UIManager;
import javax.swing.WindowConstants;

// TODO move to optaplanner-swingwb, the Swing version of optaplanner-wb (which doesn't exist yet either)
public class SwingUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {

    public static void register() {
        SwingUncaughtExceptionHandler exceptionHandler = new SwingUncaughtExceptionHandler();
        Thread.setDefaultUncaughtExceptionHandler(exceptionHandler);
        System.setProperty("sun.awt.exception.handler", SwingUncaughtExceptionHandler.class.getName());
    }

    @Override
    public void uncaughtException(Thread t, Throwable e) {
        // Not logger.error() because it needs to show up red (and linked) in the IDE console
        System.err.append("Exception in thread \"").append(t.getName()).append("\" ");
        e.printStackTrace();
        displayException(t, e);
    }

    private void displayException(Thread t, Throwable e) {
        final JFrame exceptionFrame = new JFrame("Uncaught exception: " + e.getMessage());
        Icon errorIcon = UIManager.getIcon("OptionPane.errorIcon");
        BufferedImage errorImage = new BufferedImage(
                errorIcon.getIconWidth(), errorIcon.getIconHeight(), BufferedImage.TYPE_INT_RGB);
        errorIcon.paintIcon(null, errorImage.getGraphics(), 0, 0);
        exceptionFrame.setIconImage(errorImage);
        exceptionFrame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
        JPanel contentPanel = new JPanel(new BorderLayout(5, 5));
        contentPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
        contentPanel.add(new JLabel("An uncaught exception has occurred: "), BorderLayout.NORTH);
        JTextArea stackTraceTextArea = new JTextArea(10, 80);
        stackTraceTextArea.setEditable(false);
        stackTraceTextArea.append("Exception in thread \"" + t.getName() + "\" " + e.getClass().getName()
                + ": " + e.getMessage() + "\n");
        for (StackTraceElement stackTraceElement : e.getStackTrace()) {
            stackTraceTextArea.append("    at " + stackTraceElement.toString() + "\n");
        }
        Throwable parentException = e;
        Throwable cause = e.getCause();
        while (cause != null && cause != parentException) {
            stackTraceTextArea.append("Caused by: " + "\" " + e.getClass().getName()
                    + ": " + e.getMessage() + "\n");
            for (StackTraceElement stackTraceElement : e.getStackTrace()) {
                stackTraceTextArea.append("    at " + stackTraceElement.toString() + "\n");
            }
            parentException = cause;
            cause = cause.getCause();
        }
        JScrollPane stackTraceScrollPane = new JScrollPane(stackTraceTextArea,
                ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
        contentPanel.add(stackTraceScrollPane, BorderLayout.CENTER);
        stackTraceTextArea.setCaretPosition(0); // Scroll to top
        JButton closeButton = new JButton(new AbstractAction("Close") {
            @Override
            public void actionPerformed(ActionEvent e) {
                exceptionFrame.setVisible(false);
                exceptionFrame.dispose();
            }
        });
        contentPanel.add(closeButton, BorderLayout.SOUTH);
        exceptionFrame.setContentPane(contentPanel);
        exceptionFrame.pack();
        exceptionFrame.setLocationRelativeTo(null);
        exceptionFrame.setVisible(true);
    }

}

@@ -2812,17 +2812,17 @@
 extArea(
-1
+3
 0, 80);%0A
@@ -3386,32 +3386,36 @@
 by: %22 + %22%5C%22 %22 + 
+caus
 e.getClass().get
@@ -3442,32 +3442,36 @@
        + %22: %22 + 
+caus
 e.getMessage() +

Fix ExceptionHandler: show causes properly