// Path: easymvp-api/src/main/java/easymvp/Presenter.java
// public interface Presenter<V> {
// 
//     /**
//      * Called when the view attached to the screen.
//      * <p>
//      * This method will be invoked during {@link android.app.Activity#onStart()}, {@link android.app.Fragment#onResume()}
//      * and {@link android.view.View#onAttachedToWindow()}.
//      * @param view the view that the presenter interacts with
//      */
//     void onViewAttached(V view);
// 
//     /**
//      * Called when the view detached from the screen.
//      * <p>
//      * This method will be invoked during {@link android.app.Activity#onStop()}, {@link android.app.Fragment#onPause()}
//      * and {@link android.view.View#onDetachedFromWindow()}.
//      */
//     void onViewDetached();
// 
//     /**
//      * Called when a user leaves the view completely. After the invocation of this method, presenter instance will be destroyed.
//      * <p>
//      * Note that on configuration changes like rotation, presenter instance will be alive.
//      */
//     void onDestroyed();
// 
//     /**
//      * @return Returns true if the view is currently attached to the presenter, otherwise returns false.
//      **/
//     boolean isViewAttached();
// 
//     /**
//      * @return Returns the attached view. If view is already detached, null will be returned.
//      */
//     @Nullable
//     V getView();
// }
// 
// Path: easymvp-compiler/src/main/java/easymvp/compiler/util/ClassNames.java
// public static final ClassName CONTEXT = ClassName.get("android.content", "Context");
// 
// Path: easymvp-compiler/src/main/java/easymvp/compiler/util/ClassNames.java
// public static final ClassName PROVIDER = ClassName.get("javax.inject", "Provider");


import com.squareup.javapoet.FieldSpec;
import com.squareup.javapoet.JavaFile;
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.ParameterSpec;
import com.squareup.javapoet.ParameterizedTypeName;
import com.squareup.javapoet.TypeName;
import com.squareup.javapoet.TypeSpec;
import com.squareup.javapoet.TypeVariableName;
import javax.lang.model.element.Modifier;
import easymvp.Presenter;
import static easymvp.compiler.util.ClassNames.CONTEXT;
import static easymvp.compiler.util.ClassNames.PROVIDER;
    private static final String FIELD_PRESENTER_FACTORY = "presenterFactory";
    //All methods that MUST be implemented
    private static final String METHOD_ON_START_LOADING = "onStartLoading";
    private static final String METHOD_ON_FORCE_LOAD = "onForceLoad";
    private static final String METHOD_ON_RESET = "onReset";

    private boolean supportLibrary;

    public PresenterLoaderGenerator(boolean supportLibrary) {
        super(AndroidLoaderUtils.getPresenterLoader(supportLibrary).packageName(),
              AndroidLoaderUtils.getPresenterLoader(supportLibrary).simpleName());
        this.supportLibrary = supportLibrary;
    }

    @Override
    public JavaFile build() {
        TypeSpec.Builder result =
                TypeSpec.classBuilder(getClassName()).addModifiers(Modifier.PUBLIC)
                        .addTypeVariable(TypeVariableName.get("P", Presenter.class))
                        .superclass(ParameterizedTypeName.get(AndroidLoaderUtils.getLoader(supportLibrary),
                                                              TypeVariableName.get("P")));
        addConstructor(result);
        addFields(result);
        addMethods(result);
        return JavaFile.builder(getPackageName(), result.build())
                .addFileComment("Generated class from EasyMVP. Do not modify!").build();
    }

    private void addConstructor(TypeSpec.Builder result) {
        result.addMethod(MethodSpec.constructorBuilder()
// Path: easymvp-api/src/main/java/easymvp/Presenter.java
// public interface Presenter<V> {
// 
//     /**
//      * Called when the view attached to the screen.
//      * <p>
//      * This method will be invoked during {@link android.app.Activity#onStart()}, {@link android.app.Fragment#onResume()}
//      * and {@link android.view.View#onAttachedToWindow()}.
//      * @param view the view that the presenter interacts with
//      */
//     void onViewAttached(V view);
// 
//     /**
//      * Called when the view detached from the screen.
//      * <p>
//      * This method will be invoked during {@link android.app.Activity#onStop()}, {@link android.app.Fragment#onPause()}
//      * and {@link android.view.View#onDetachedFromWindow()}.
//      */
//     void onViewDetached();
// 
//     /**
//      * Called when a user leaves the view completely. After the invocation of this method, presenter instance will be destroyed.
//      * <p>
//      * Note that on configuration changes like rotation, presenter instance will be alive.
//      */
//     void onDestroyed();
// 
//     /**
//      * @return Returns true if the view is currently attached to the presenter, otherwise returns false.
//      **/
//     boolean isViewAttached();
// 
//     /**
//      * @return Returns the attached view. If view is already detached, null will be returned.
//      */
//     @Nullable
//     V getView();
// }
// 
// Path: easymvp-compiler/src/main/java/easymvp/compiler/util/ClassNames.java
// public static final ClassName CONTEXT = ClassName.get("android.content", "Context");
// 
// Path: easymvp-compiler/src/main/java/easymvp/compiler/util/ClassNames.java
// public static final ClassName PROVIDER = ClassName.get("javax.inject", "Provider");


// Path: easymvp-compiler/src/main/java/easymvp/compiler/generator/PresenterLoaderGenerator.java
import com.squareup.javapoet.FieldSpec;
import com.squareup.javapoet.JavaFile;
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.ParameterSpec;
import com.squareup.javapoet.ParameterizedTypeName;
import com.squareup.javapoet.TypeName;
import com.squareup.javapoet.TypeSpec;
import com.squareup.javapoet.TypeVariableName;
import javax.lang.model.element.Modifier;
import easymvp.Presenter;
import static easymvp.compiler.util.ClassNames.CONTEXT;
import static easymvp.compiler.util.ClassNames.PROVIDER;

    private static final String FIELD_PRESENTER_FACTORY = "presenterFactory";
    //All methods that MUST be implemented
    private static final String METHOD_ON_START_LOADING = "onStartLoading";
    private static final String METHOD_ON_FORCE_LOAD = "onForceLoad";
    private static final String METHOD_ON_RESET = "onReset";

    private boolean supportLibrary;

    public PresenterLoaderGenerator(boolean supportLibrary) {
        super(AndroidLoaderUtils.getPresenterLoader(supportLibrary).packageName(),
              AndroidLoaderUtils.getPresenterLoader(supportLibrary).simpleName());
        this.supportLibrary = supportLibrary;
    }

    @Override
    public JavaFile build() {
        TypeSpec.Builder result =
                TypeSpec.classBuilder(getClassName()).addModifiers(Modifier.PUBLIC)
                        .addTypeVariable(TypeVariableName.get("P", Presenter.class))
                        .superclass(ParameterizedTypeName.get(AndroidLoaderUtils.getLoader(supportLibrary),
                                                              TypeVariableName.get("P")));
        addConstructor(result);
        addFields(result);
        addMethods(result);
        return JavaFile.builder(getPackageName(), result.build())
                .addFileComment("Generated class from EasyMVP. Do not modify!").build();
    }

    private void addConstructor(TypeSpec.Builder result) {
        result.addMethod(MethodSpec.constructorBuilder()
                                 .addParameter(CONTEXT, "context")