/*
 * Copyright (c) 2013 Fizz Buzz LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.fizzbuzz.android.dagger;

import android.app.Application;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import dagger.Module;
import dagger.ObjectGraph;
import dagger.Provides;

import javax.inject.Qualifier;
import javax.inject.Singleton;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.util.ArrayList;
import java.util.List;

import static com.fizzbuzz.android.dagger.Preconditions.checkState;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
 * Manages an ObjectGraph on behalf of an Application.
 */
public abstract class InjectingApplication
        extends Application
        implements Injector {

    private ObjectGraph mObjectGraph;

    /**
     * Creates an object graph for this Application using the modules returned by {@link #getModules()}.
     * <p/>
     * Injects this Application using the created graph.
     */
    @Override
    public void onCreate() {
        super.onCreate();

        // initialize object graph and inject this
        mObjectGraph = ObjectGraph.create(getModules().toArray());
        mObjectGraph.inject(this);

        // debug mode stuff
        if ((getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE) == 1) {
            mObjectGraph.validate(); // validate dagger's object graph
        }
    }

    /**
     * Gets this Application's object graph.
     *
     * @return the object graph
     */
    @Override
    public ObjectGraph getObjectGraph() {
        return mObjectGraph;
    }

    /**
     * Injects a target object using this Application's object graph.
     *
     * @param target the target object
     */
    public void inject(Object target) {
        checkState(mObjectGraph != null, "object graph must be initialized prior to calling inject");
        mObjectGraph.inject(target);
    }

    /**
     * Returns the list of dagger modules to be included in this Application's object graph.  Subclasses that override
     * this method should add to the list returned by super.getModules().
     *
     * @return the list of modules
     */
    protected List<Object> getModules() {
        List<Object> result = new ArrayList<Object>();
        result.add(new InjectingApplicationModule(this, this));
        return result;
    }

    /**
     * The dagger module associated with {@link InjectingApplication}
     */
    @Module(library = true)
    public static class InjectingApplicationModule {
        android.app.Application mApp;
        Injector mInjector;

        /**
         * Class constructor.
         *
         * @param app the Application with which this module is associated
         * @param injector the dagger injector for the Application-scope graph
         */
        public InjectingApplicationModule(android.app.Application app, Injector injector) {
            mApp = app;
            mInjector = injector;
        }

        /**
         * Provides the Application Context associated with this module's graph.
         *
         * @return the Application Context
         */
        @Provides
        @Singleton
        @Application
        public Context provideApplicationContext() {
            return mApp.getApplicationContext();
        }

        /**
         * Provides the Application
         *
         * @return the Application
         */
        @Provides
        @Singleton
        public android.app.Application provideApplication() {
            return mApp;
        }

        /**
         * Provides the Injector for the Application-scope graph
         *
         * @return the Injector
         */
        @Provides
        @Singleton
        @Application
        public Injector provideApplicationInjector() {
            return mInjector;
        }

        /**
         * Defines an qualifier annotation which can be used in conjunction with a type to identify dependencies within
         * this module's object graph.
         *
         * @see <a href="http://square.github.io/dagger/">the dagger documentation</a>
         */
        @Qualifier
        @Target({FIELD, PARAMETER, METHOD})
        @Documented
        @Retention(RUNTIME)
        public @interface Application {
        }
    }
}

@@ -1510,33 +1510,198 @@
 ate 
-ObjectGraph mObjectGraph;
+List%3CObject%3E mSeedModules = new ArrayList%3CObject%3E();%0A    private ObjectGraph mObjectGraph;%0A%0A    public void addSeedModules(List%3CObject%3E modules) %7B%0A        mSeedModules.addAll(modules);%0A    %7D
 %0A%0A  
@@ -3165,24 +3165,61 @@
 %3CObject%3E();%0A
+        result.addAll(mSeedModules);%0A
         resu

add support for seeding modules into an InjectingApplication prior to the call to onCreate