/*
 * @author Ranides Atterwim <ranides@gmail.com>
 * @copyright Ranides Atterwim
 * @license WTFPL
 * @url http://ranides.net/projects/assira
 */
package net.ranides.assira.awt;

import java.applet.Applet;
import java.awt.EventQueue;
import java.awt.Frame;
import java.awt.Window;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.lang.reflect.InvocationTargetException;
import java.util.function.Consumer;
import javax.swing.SwingUtilities;
import net.ranides.assira.events.Events;
import net.ranides.assira.trace.LoggerUtils;


public final class AWTInvoker {
    
    private static final org.slf4j.Logger LOGGER = LoggerUtils.getLogger();
    
    private AWTInvoker() {
        // utility class
    }

    public static void run(boolean sync, Runnable action, Consumer<? super Events.Failure> handler) {
        Runnable runnable = () -> {
            try {
                action.run();
            } catch(Exception e) {
                handler.accept(Events.failure(e));
            }
        };
        try {
            if(sync) {
                if( EventQueue.isDispatchThread() ) {
                    runnable.run();
                } else {
                    SwingUtilities.invokeAndWait(runnable);
                }
            } else {
                SwingUtilities.invokeLater(runnable);
            }
        } catch(InterruptedException cause) {
            handler.accept(Events.failure(cause));
        } catch (InvocationTargetException cause) {
            throw new AssertionError("FATAL ERROR", cause);
        }
    }
    
    public static void run(boolean sync, Runnable action) {
        run(sync, action, cause -> {
            LOGGER.error("Unexpected exception in AWT thread. Action: {}", cause, action);
        });
    }

    /**
     * Metoda pomocnicza, otwiera nowe okno {@link Window} wewnątrz którego jest
     * umieszczony podany aplet.
     * @param applet
     * @param title
     * @param width
     * @param height 
     * @return okno, zawierające zagnieżdżony i uruchomiony aplet
     */
    public static Window runApplet(final Applet applet, final String title, final int width, final int height) {
        final Frame frame = new Frame(title);
        // allow some extra room for the frame title bar.
        frame.setSize(width + 16, height + 36);
        frame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent event) {
                applet.stop();
                applet.destroy();
                System.exit(0);
            }
        });
        frame.add(applet);
        applet.init();
        frame.validate();
        frame.setVisible(true);
        applet.start();
        return frame;
    }
    
}
