// Path: core/src/main/java/pocketbus/SubscriptionRegistration.java
// public interface SubscriptionRegistration {
//     /**
//      * @return a list of subscriptions
//      */
//     List<Subscription<?>> getSubscriptions();
// }
// 
// Path: core/src/main/java/pocketbus/Subscription.java
// public interface Subscription<T> {
//     /**
//      * Handle an event posted to the bus
//      *
//      * @param t event posted to the bus
//      * @return false if subscription should be unregistered
//      */
//     boolean handle(T t);
// 
//     /**
//      * @return Class of event this subscription handles
//      */
//     Class<T> getEventClass();
// 
//     /**
//      * @return ThreadMode for this subscription
//      */
//     ThreadMode getThreadMode();
// 
//     /**
//      * @return the target with which this subscription interacts
//      */
//     <E> E getTarget();
// }
// 
// Path: core/src/main/java/pocketbus/ThreadMode.java
// public enum ThreadMode {
//     /**
//      * Subscription run on same thread as caller
//      */
//     CURRENT, // Schedulers.trampoline()
//     /**
//      * Subscription run on the main thread
//      */
//     MAIN, // AndroidSchedulers.mainThread()
//     /**
//      * Subscription run on a background thread
//      */
//     BACKGROUND // Schedulers.newThread()
// }
// 
// Path: core/src/main/java/pocketbus/internal/PocketBusConst.java
// public class PocketBusConst {
//     public static final String ANDROID_PREFIX = "android.";
//     public static final String JAVA_PREFIX = "java.";
// 
//     public static final String REGISTRATION_SUFFIX = "SubscriptionRegistration";
//     public static final String REGISTRY_NAME = "BusRegistry";
// 
//     public static final String METHOD_HANDLE = "handle";
//     public static final String METHOD_GET_SUBSCRIPTIONS = "getSubscriptions";
//     public static final String METHOD_GET_EVENT_CLASS = "getEventClass";
//     public static final String METHOD_GET_THREAD_MODE = "getThreadMode";
//     public static final String METHOD_GET_TARGET = "getTarget";
//     public static final String METHOD_EQUALS = "equals";
//     public static final String METHOD_GET_REGISTRAR = "getRegistration";
// 
//     public static final String VAR_TARGET_REF = "targetRef";
//     public static final String VAR_TARGET = "target";
//     public static final String VAR_EVENT = "event";
//     public static final String VAR_SUBSCRIPTION = "subscription";
//     public static final String VAR_SUBSCRIPTIONS = "subscriptions";
//     public static final String VAR_O = "o";
// }


import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.FieldSpec;
import com.squareup.javapoet.JavaFile;
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.ParameterizedTypeName;
import com.squareup.javapoet.TypeName;
import com.squareup.javapoet.TypeSpec;
import com.squareup.javapoet.WildcardTypeName;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import javax.lang.model.element.Modifier;
import javax.lang.model.type.TypeMirror;
import pocketbus.SubscriptionRegistration;
import pocketbus.Subscription;
import pocketbus.ThreadMode;
import pocketbus.internal.PocketBusConst;
    private void generateHandleMethod(TypeSpec.Builder classBuilder, SubscriptionMethod subscriptionMethod) {
        MethodSpec.Builder methodBuilder = MethodSpec.methodBuilder(PocketBusConst.METHOD_HANDLE)
                .addModifiers(Modifier.PUBLIC)
                .addAnnotation(Override.class)
                .addParameter(TypeName.get(subscriptionMethod.getEventType()), PocketBusConst.VAR_EVENT)
                .returns(TypeName.BOOLEAN)
                .addStatement("$T $N = $N.get()", TypeName.get(targetType), PocketBusConst.VAR_TARGET, PocketBusConst.VAR_TARGET_REF)
                .beginControlFlow("if ($N != null)", PocketBusConst.VAR_TARGET)
                .addStatement("$N.$L($N)", PocketBusConst.VAR_TARGET, subscriptionMethod.getName(), PocketBusConst.VAR_EVENT)
                .endControlFlow()
                .addStatement("return $N != null", PocketBusConst.VAR_TARGET)
                ;

        classBuilder.addMethod(methodBuilder.build());
    }

    private void generateClassMethod(TypeSpec.Builder classBuilder, SubscriptionMethod subscription) {
        MethodSpec.Builder methodBuilder = MethodSpec.methodBuilder(PocketBusConst.METHOD_GET_EVENT_CLASS)
                .addModifiers(Modifier.PUBLIC)
                .addAnnotation(Override.class)
                .returns(ParameterizedTypeName.get(ClassName.get(Class.class), TypeName.get(subscription.getEventType())))
                .addStatement("return $T.class", TypeName.get(subscription.getEventType()));

        classBuilder.addMethod(methodBuilder.build());
    }

    private void generateThreadMethod(TypeSpec.Builder classBuilder, SubscriptionMethod subscription) {
        MethodSpec.Builder methodBuilder = MethodSpec.methodBuilder(PocketBusConst.METHOD_GET_THREAD_MODE)
                .addModifiers(Modifier.PUBLIC)
                .addAnnotation(Override.class)
// Path: core/src/main/java/pocketbus/SubscriptionRegistration.java
// public interface SubscriptionRegistration {
//     /**
//      * @return a list of subscriptions
//      */
//     List<Subscription<?>> getSubscriptions();
// }
// 
// Path: core/src/main/java/pocketbus/Subscription.java
// public interface Subscription<T> {
//     /**
//      * Handle an event posted to the bus
//      *
//      * @param t event posted to the bus
//      * @return false if subscription should be unregistered
//      */
//     boolean handle(T t);
// 
//     /**
//      * @return Class of event this subscription handles
//      */
//     Class<T> getEventClass();
// 
//     /**
//      * @return ThreadMode for this subscription
//      */
//     ThreadMode getThreadMode();
// 
//     /**
//      * @return the target with which this subscription interacts
//      */
//     <E> E getTarget();
// }
// 
// Path: core/src/main/java/pocketbus/ThreadMode.java
// public enum ThreadMode {
//     /**
//      * Subscription run on same thread as caller
//      */
//     CURRENT, // Schedulers.trampoline()
//     /**
//      * Subscription run on the main thread
//      */
//     MAIN, // AndroidSchedulers.mainThread()
//     /**
//      * Subscription run on a background thread
//      */
//     BACKGROUND // Schedulers.newThread()
// }
// 
// Path: core/src/main/java/pocketbus/internal/PocketBusConst.java
// public class PocketBusConst {
//     public static final String ANDROID_PREFIX = "android.";
//     public static final String JAVA_PREFIX = "java.";
// 
//     public static final String REGISTRATION_SUFFIX = "SubscriptionRegistration";
//     public static final String REGISTRY_NAME = "BusRegistry";
// 
//     public static final String METHOD_HANDLE = "handle";
//     public static final String METHOD_GET_SUBSCRIPTIONS = "getSubscriptions";
//     public static final String METHOD_GET_EVENT_CLASS = "getEventClass";
//     public static final String METHOD_GET_THREAD_MODE = "getThreadMode";
//     public static final String METHOD_GET_TARGET = "getTarget";
//     public static final String METHOD_EQUALS = "equals";
//     public static final String METHOD_GET_REGISTRAR = "getRegistration";
// 
//     public static final String VAR_TARGET_REF = "targetRef";
//     public static final String VAR_TARGET = "target";
//     public static final String VAR_EVENT = "event";
//     public static final String VAR_SUBSCRIPTION = "subscription";
//     public static final String VAR_SUBSCRIPTIONS = "subscriptions";
//     public static final String VAR_O = "o";
// }


// Path: compiler/src/main/java/pocketbus/internal/codegen/SubscriptionGenerator.java
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.FieldSpec;
import com.squareup.javapoet.JavaFile;
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.ParameterizedTypeName;
import com.squareup.javapoet.TypeName;
import com.squareup.javapoet.TypeSpec;
import com.squareup.javapoet.WildcardTypeName;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import javax.lang.model.element.Modifier;
import javax.lang.model.type.TypeMirror;
import pocketbus.SubscriptionRegistration;
import pocketbus.Subscription;
import pocketbus.ThreadMode;
import pocketbus.internal.PocketBusConst;

    private void generateHandleMethod(TypeSpec.Builder classBuilder, SubscriptionMethod subscriptionMethod) {
        MethodSpec.Builder methodBuilder = MethodSpec.methodBuilder(PocketBusConst.METHOD_HANDLE)
                .addModifiers(Modifier.PUBLIC)
                .addAnnotation(Override.class)
                .addParameter(TypeName.get(subscriptionMethod.getEventType()), PocketBusConst.VAR_EVENT)
                .returns(TypeName.BOOLEAN)
                .addStatement("$T $N = $N.get()", TypeName.get(targetType), PocketBusConst.VAR_TARGET, PocketBusConst.VAR_TARGET_REF)
                .beginControlFlow("if ($N != null)", PocketBusConst.VAR_TARGET)
                .addStatement("$N.$L($N)", PocketBusConst.VAR_TARGET, subscriptionMethod.getName(), PocketBusConst.VAR_EVENT)
                .endControlFlow()
                .addStatement("return $N != null", PocketBusConst.VAR_TARGET)
                ;

        classBuilder.addMethod(methodBuilder.build());
    }

    private void generateClassMethod(TypeSpec.Builder classBuilder, SubscriptionMethod subscription) {
        MethodSpec.Builder methodBuilder = MethodSpec.methodBuilder(PocketBusConst.METHOD_GET_EVENT_CLASS)
                .addModifiers(Modifier.PUBLIC)
                .addAnnotation(Override.class)
                .returns(ParameterizedTypeName.get(ClassName.get(Class.class), TypeName.get(subscription.getEventType())))
                .addStatement("return $T.class", TypeName.get(subscription.getEventType()));

        classBuilder.addMethod(methodBuilder.build());
    }

    private void generateThreadMethod(TypeSpec.Builder classBuilder, SubscriptionMethod subscription) {
        MethodSpec.Builder methodBuilder = MethodSpec.methodBuilder(PocketBusConst.METHOD_GET_THREAD_MODE)
                .addModifiers(Modifier.PUBLIC)
                .addAnnotation(Override.class)
                .returns(TypeName.get(ThreadMode.class))