package com.bugsnag;

import java.lang.Thread.UncaughtExceptionHandler;
import java.util.Set;
import java.util.WeakHashMap;


class ExceptionHandler implements UncaughtExceptionHandler {
    private final UncaughtExceptionHandler originalHandler;
    private final WeakHashMap<Bugsnag, Boolean> clientMap = new WeakHashMap<Bugsnag, Boolean>();

    Set<Bugsnag> uncaughtExceptionClients() {
        return clientMap.keySet();
    }

    static void enable(Bugsnag bugsnag) {
        UncaughtExceptionHandler currentHandler = Thread.getDefaultUncaughtExceptionHandler();

        // Find or create the Bugsnag ExceptionHandler
        ExceptionHandler bugsnagHandler;
        if (currentHandler instanceof ExceptionHandler) {
            bugsnagHandler = (ExceptionHandler) currentHandler;
        } else {
            bugsnagHandler = new ExceptionHandler(currentHandler);
            Thread.setDefaultUncaughtExceptionHandler(bugsnagHandler);
        }

        // Subscribe this bugsnag to uncaught exceptions
        bugsnagHandler.clientMap.put(bugsnag, true);
    }

    static void disable(Bugsnag bugsnag) {
        // Find the Bugsnag ExceptionHandler
        UncaughtExceptionHandler currentHandler = Thread.getDefaultUncaughtExceptionHandler();
        if (currentHandler instanceof ExceptionHandler) {
            // Unsubscribe this bugsnag from uncaught exceptions
            ExceptionHandler bugsnagHandler = (ExceptionHandler) currentHandler;
            bugsnagHandler.clientMap.remove(bugsnag);

            // Remove the Bugsnag ExceptionHandler if no clients are subscribed
            if (bugsnagHandler.clientMap.size() == 0) {
                Thread.setDefaultUncaughtExceptionHandler(bugsnagHandler.originalHandler);
            }
        }
    }

    ExceptionHandler(UncaughtExceptionHandler originalHandler) {
        this.originalHandler = originalHandler;
    }

    @Override
    public void uncaughtException(Thread thread, Throwable throwable) {
        // Notify any subscribed clients of the uncaught exception
        for (Bugsnag bugsnag : clientMap.keySet()) {

            HandledState handledState = HandledState.newInstance(
                    HandledState.SeverityReasonType.REASON_UNHANDLED_EXCEPTION, Severity.ERROR);
            bugsnag.notify(throwable, handledState, thread);
        }

        // Pass exception on to original exception handler
        if (originalHandler != null) {
            originalHandler.uncaughtException(thread, throwable);
        } else {
            // Emulate the java exception print style
            System.err.printf("Exception in thread \"%s\" ", thread.getName());
            throwable.printStackTrace(System.err);
        }
    }
}

@@ -2091,17 +2091,89 @@
 et()) %7B%0A
-%0A
+            if (bugsnag.getConfig().shouldSendUncaughtExceptions()) %7B%0A   
         
@@ -2168,32 +2168,33 @@
 %0A               
+ 
 HandledState han
@@ -2231,16 +2231,20 @@
 stance(%0A
+    
         
@@ -2340,24 +2340,28 @@
             
+ 
+   
 bugsnag.noti
@@ -2397,16 +2397,30 @@
 hread);%0A
+            %7D%0A
         

disable uncaughtExceptionHandler if sendUncaughtExceptions is set after initialisation