// 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;
package pocketbus.internal.codegen;





public class SubscriptionGenerator {

    private static final ParameterizedTypeName SUBSCRIPTION_TYPE = ParameterizedTypeName.get(ClassName.get(Subscription.class),
            WildcardTypeName.subtypeOf(TypeName.OBJECT));
    private static final ParameterizedTypeName LIST_TYPE = ParameterizedTypeName.get(ClassName.get(List.class), SUBSCRIPTION_TYPE);

    Set<SubscriptionMethod> methods = new LinkedHashSet<>();

    private final String classPackage;
    private final String className;
    private final TypeMirror targetType;
    private ClassName parentAdapter;
    private int idx = 1;

    public SubscriptionGenerator(String classPackage, String className, TypeMirror targetType) {
        this.classPackage = classPackage;
        this.className = className;
        this.targetType = targetType;
    }

    public boolean addMethod(SubscriptionMethod method) {
        method.setIndex(idx++);
        return this.methods.add(method);
    }

    public JavaFile generate() {
        TypeSpec.Builder classBuilder = TypeSpec.classBuilder(className)
                .addModifiers(Modifier.PUBLIC)
// 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;

package pocketbus.internal.codegen;





public class SubscriptionGenerator {

    private static final ParameterizedTypeName SUBSCRIPTION_TYPE = ParameterizedTypeName.get(ClassName.get(Subscription.class),
            WildcardTypeName.subtypeOf(TypeName.OBJECT));
    private static final ParameterizedTypeName LIST_TYPE = ParameterizedTypeName.get(ClassName.get(List.class), SUBSCRIPTION_TYPE);

    Set<SubscriptionMethod> methods = new LinkedHashSet<>();

    private final String classPackage;
    private final String className;
    private final TypeMirror targetType;
    private ClassName parentAdapter;
    private int idx = 1;

    public SubscriptionGenerator(String classPackage, String className, TypeMirror targetType) {
        this.classPackage = classPackage;
        this.className = className;
        this.targetType = targetType;
    }

    public boolean addMethod(SubscriptionMethod method) {
        method.setIndex(idx++);
        return this.methods.add(method);
    }

    public JavaFile generate() {
        TypeSpec.Builder classBuilder = TypeSpec.classBuilder(className)
                .addModifiers(Modifier.PUBLIC)
                .addField(getWeakReferenceType(), PocketBusConst.VAR_TARGET_REF, Modifier.PRIVATE, Modifier.FINAL)