// 
// Decompiled by Procyon v0.6.0
// 

package org.jline.utils;

import java.lang.reflect.Method;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Proxy;
import java.util.Objects;

public final class Signals
{
    private Signals() {
    }
    
    public static Object register(final String name, final Runnable handler) {
        Objects.requireNonNull(handler);
        return register(name, handler, handler.getClass().getClassLoader());
    }
    
    public static Object register(final String name, final Runnable handler, final ClassLoader loader) {
        try {
            final Class<?> signalHandlerClass = Class.forName("sun.misc.SignalHandler");
            final Object signalHandler = Proxy.newProxyInstance(loader, new Class[] { signalHandlerClass }, (proxy, method, args) -> {
                if (method.getDeclaringClass() == Object.class) {
                    if ("toString".equals(method.getName())) {
                        return handler.toString();
                    }
                }
                else if (method.getDeclaringClass() == signalHandlerClass) {
                    Log.trace(() -> "Calling handler " + toString(handler) + " for signal " + name);
                    handler.run();
                }
                return null;
            });
            return doRegister(name, signalHandler);
        }
        catch (final Exception e) {
            Log.debug("Error registering handler for signal ", name, e);
            return null;
        }
    }
    
    public static Object registerDefault(final String name) {
        try {
            final Class<?> signalHandlerClass = Class.forName("sun.misc.SignalHandler");
            return doRegister(name, signalHandlerClass.getField("SIG_DFL").get(null));
        }
        catch (final Exception e) {
            Log.debug("Error registering default handler for signal ", name, e);
            return null;
        }
    }
    
    public static void unregister(final String name, final Object previous) {
        try {
            if (previous != null) {
                doRegister(name, previous);
            }
        }
        catch (final Exception e) {
            Log.debug("Error unregistering handler for signal ", name, e);
        }
    }
    
    private static Object doRegister(final String name, final Object handler) throws Exception {
        Log.trace(() -> "Registering signal " + name + " with handler " + toString(handler));
        final Class<?> signalClass = Class.forName("sun.misc.Signal");
        final Constructor<?> constructor = signalClass.getConstructor(String.class);
        Object signal;
        try {
            signal = constructor.newInstance(name);
        }
        catch (final InvocationTargetException e) {
            if (e.getCause() instanceof IllegalArgumentException) {
                Log.trace(() -> "Ignoring unsupported signal " + name);
            }
            else {
                Log.debug("Error registering handler for signal ", name, e);
            }
            return null;
        }
        final Class<?> signalHandlerClass = Class.forName("sun.misc.SignalHandler");
        return signalClass.getMethod("handle", signalClass, signalHandlerClass).invoke(null, signal, handler);
    }
    
    private static String toString(final Object handler) {
        try {
            final Class<?> signalHandlerClass = Class.forName("sun.misc.SignalHandler");
            if (handler == signalHandlerClass.getField("SIG_DFL").get(null)) {
                return "SIG_DFL";
            }
            if (handler == signalHandlerClass.getField("SIG_IGN").get(null)) {
                return "SIG_IGN";
            }
        }
        catch (final Throwable t) {}
        return (handler != null) ? handler.toString() : "null";
    }
}
