package io.threadannotations.internal;

import java.lang.ref.WeakReference;
import java.util.concurrent.ConcurrentHashMap;

import javax.swing.SwingUtilities;

import io.threadannotations.MultiThread;
import io.threadannotations.SingleThread;
import io.threadannotations.SwingThread;

public class InterceptionObjectImpl implements InterceptionObject {

    static final String SWING_THREAD_ANNOTATION_NAME = SwingThread.class.getName();
    static final String SINGLE_THREAD_ANNOTATION_NAME = SingleThread.class.getName();
    static final String MULTI_THREAD_ANNOTATION_NAME = MultiThread.class.getName();

    private final ConcurrentHashMap<Integer, WeakReference<Thread>> singleThreadMap = new ConcurrentHashMap<>();

    @Override
    public void intercept(String classAnnotation, int caThreadId, String methodAnnotation, int maThreadId) {
        if (methodAnnotation.equals(SWING_THREAD_ANNOTATION_NAME)) {
            handleSwingThread();
        } else if (methodAnnotation.equals(SINGLE_THREAD_ANNOTATION_NAME)) {
            handleSingleThread(maThreadId);
        } else if (!methodAnnotation.equals(MULTI_THREAD_ANNOTATION_NAME)) {
            if (classAnnotation.equals(SWING_THREAD_ANNOTATION_NAME)) {
                handleSwingThread();
            } else if (classAnnotation.equals(SINGLE_THREAD_ANNOTATION_NAME)) {
                handleSingleThread(caThreadId);
            }
        }
    }

    private void handleSingleThread(int threadId) {
        Thread currentThread = Thread.currentThread();
        if (singleThreadMap.putIfAbsent(threadId, new WeakReference<>(currentThread)) != null) {
            Thread expected = singleThreadMap.get(threadId).get();
            if (expected == null) {
                throw new IllegalStateException("Expected call from already garbage-collected thread, was called from "
                        + currentThread.getName());
            } else if (!expected.equals(currentThread)) {
                throw new IllegalStateException("Expected call from " + expected.getName() + ", was called from "
                        + currentThread.getName());
            }
        }
    }

    private void handleSwingThread() {
        if (!SwingUtilities.isEventDispatchThread()) {
            throw new IllegalStateException("Expected call from Swing-thread, was called from "
                    + Thread.currentThread().getName());
        }
    }
}

@@ -847,30 +847,31 @@
         if (
-method
+!handle
 Annotation.e
@@ -872,284 +872,190 @@
 tion
-.equals(SWING_THREAD_ANNOTATION_NAME)) %7B%0A            handleSwingThread();%0A        %7D else if (methodAnnotation.equals(SINGLE_THREAD_ANNOTATION_NAME)) %7B%0A            handleSingleThread(maThreadId);%0A        %7D else if (!methodAnnotation.equals(MULTI_THREAD_ANNOTATION_NAME)) %7B%0A    
+(methodAnnotation, maThreadId)) %7B%0A            handleAnnotation(classAnnotation, caThreadId);%0A        %7D%0A    %7D%0A%0A    private boolean handleAnnotation(String annotation, int threadId) %7B%0A
     
@@ -1058,30 +1058,25 @@
         if (
-classA
+a
 nnotation.eq
@@ -1121,28 +1121,24 @@
             
-   
- 
 handleSwingT
@@ -1142,32 +1142,53 @@
 ngThread();%0A    
+        return true;%0A
         %7D else i
@@ -1190,22 +1190,17 @@
 lse if (
-classA
+a
 nnotatio
@@ -1250,28 +1250,24 @@
             
-    
 handleSingle
@@ -1273,19 +1273,17 @@
 eThread(
-caT
+t
 hreadId)
@@ -1292,35 +1292,111 @@
             
-%7D%0A        %7D
+return true;%0A        %7D%0A%0A        return annotation.equals(MULTI_THREAD_ANNOTATION_NAME);
 %0A    %7D%0A%0A    

Refactor annotation handling in agent