content: /**
   * Copyright 2017 JessYan
   * <p>
   * 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
   * <p>
   * http://www.apache.org/licenses/LICENSE-2.0
   * <p>
   * 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 <%= appPackage %>.base.delegate;
  
  import android.app.Application;
  import android.content.ComponentCallbacks2;
  import android.content.Context;
  import android.content.res.Configuration;
  import android.support.annotation.NonNull;
  
  import <%= appPackage %>.base.App;
  import <%= appPackage %>.base.BaseApplication;
  import <%= appPackage %>.di.component.AppComponent;
  import <%= appPackage %>.di.component.DaggerAppComponent;
  import <%= appPackage %>.di.module.AppModule;
  import <%= appPackage %>.di.module.ClientModule;
  import <%= appPackage %>.di.module.GlobalConfigModule;
  import <%= appPackage %>.http.imageloader.glide.ImageConfigImpl;
  import <%= appPackage %>.integration.ActivityLifecycle;
  import <%= appPackage %>.integration.ConfigModule;
  import <%= appPackage %>.integration.ManifestParser;
  import <%= appPackage %>.integration.lifecycle.ActivityLifecycleForRxLifecycle;
  import <%= appPackage %>.utils.Preconditions;
  
  import java.util.ArrayList;
  import java.util.List;
  
  import javax.inject.Inject;
  
  /**
   * ================================================
   * AppDelegate 可以代理 Application 的生命周期,在对应的生命周期,执行对应的逻辑,因为 Java 只能单继承
   * 所以当遇到某些三方库需要继承于它的 Application 的时候,就只有自定义 Application 并继承于三方库的 Application
   * 这时就不用再继承 BaseApplication,只用在自定义Application中对应的生命周期调用AppDelegate对应的方法
   * (Application一定要实现APP接口),框架就能照常运行
   *
   * @see BaseApplication
   * @see <a href="https://github.com/JessYanCoding/MVPArms/wiki#3.12">AppDelegate wiki 官方文档</a>
   * Created by JessYan on 24/04/2017 09:44
   * <a href="mailto:jess.yan.effort@gmail.com">Contact me</a>
   * <a href="https://github.com/JessYanCoding">Follow me</a>
   * ================================================
   */
  public class AppDelegate implements App, AppLifecycles {
      private Application mApplication;
      private AppComponent mAppComponent;
      @Inject
      protected ActivityLifecycle mActivityLifecycle;
      @Inject
      protected ActivityLifecycleForRxLifecycle mActivityLifecycleForRxLifecycle;
      private List<ConfigModule> mModules;
      private List<AppLifecycles> mAppLifecycles = new ArrayList<>();
      private List<Application.ActivityLifecycleCallbacks> mActivityLifecycles = new ArrayList<>();
      private ComponentCallbacks2 mComponentCallback;
  
      public AppDelegate(Context context) {
          this.mModules = new ManifestParser(context).parse();
          for (ConfigModule module : mModules) {
              module.injectAppLifecycle(context, mAppLifecycles);
              module.injectActivityLifecycle(context, mActivityLifecycles);
          }
      }
  
      @Override
      public void attachBaseContext(Context base) {
          for (AppLifecycles lifecycle : mAppLifecycles) {
              lifecycle.attachBaseContext(base);
          }
      }
  
      @Override
      public void onCreate(Application application) {
          this.mApplication = application;
          mAppComponent = DaggerAppComponent
                  .builder()
                  .appModule(new AppModule(mApplication))//提供application
                  .clientModule(new ClientModule())//用于提供okhttp和retrofit的单例
                  .globalConfigModule(getGlobalConfigModule(mApplication, mModules))//全局配置
                  .build();
          mAppComponent.inject(this);
  
          mAppComponent.extras().put(ConfigModule.class.getName(), mModules);
  
          this.mModules = null;
  
          mApplication.registerActivityLifecycleCallbacks(mActivityLifecycle);
          mApplication.registerActivityLifecycleCallbacks(mActivityLifecycleForRxLifecycle);
  
          for (Application.ActivityLifecycleCallbacks lifecycle : mActivityLifecycles) {
              mApplication.registerActivityLifecycleCallbacks(lifecycle);
          }
  
          mComponentCallback = new AppComponentCallbacks(mApplication, mAppComponent);
  
          mApplication.registerComponentCallbacks(mComponentCallback);
  
          for (AppLifecycles lifecycle : mAppLifecycles) {
              lifecycle.onCreate(mApplication);
          }
  
      }
  
      @Override
      public void onTerminate(Application application) {
          if (mActivityLifecycle != null) {
              mApplication.unregisterActivityLifecycleCallbacks(mActivityLifecycle);
          }
          if (mActivityLifecycleForRxLifecycle != null) {
              mApplication.unregisterActivityLifecycleCallbacks(mActivityLifecycleForRxLifecycle);
          }
          if (mComponentCallback != null) {
              mApplication.unregisterComponentCallbacks(mComponentCallback);
          }
          if (mActivityLifecycles != null && mActivityLifecycles.size() > 0) {
              for (Application.ActivityLifecycleCallbacks lifecycle : mActivityLifecycles) {
                  mApplication.unregisterActivityLifecycleCallbacks(lifecycle);
              }
          }
          if (mAppLifecycles != null && mAppLifecycles.size() > 0) {
              for (AppLifecycles lifecycle : mAppLifecycles) {
                  lifecycle.onTerminate(mApplication);
              }
          }
          this.mAppComponent = null;
          this.mActivityLifecycle = null;
          this.mActivityLifecycleForRxLifecycle = null;
          this.mActivityLifecycles = null;
          this.mComponentCallback = null;
          this.mAppLifecycles = null;
          this.mApplication = null;
      }
  
  
      /**
       * 将app的全局配置信息封装进module(使用Dagger注入到需要配置信息的地方)
       * 需要在AndroidManifest中声明{@link ConfigModule}的实现类,和Glide的配置方式相似
       *
       * @return
       */
      private GlobalConfigModule getGlobalConfigModule(Context context, List<ConfigModule> modules) {
  
          GlobalConfigModule.Builder builder = GlobalConfigModule
                  .builder();
  
          for (ConfigModule module : modules) {
              module.applyOptions(context, builder);
          }
  
          return builder.build();
      }
  
  
      /**
       * 将AppComponent返回出去,供其它地方使用, AppComponent接口中声明的方法返回的实例,在getAppComponent()拿到对象后都可以直接使用
       *
       * @return
       */
      @NonNull
      @Override
      public AppComponent getAppComponent() {
          Preconditions.checkNotNull(mAppComponent,
                  "%s cannot be null,first call %s#onCreate(Application) in %s#onCreate()",
                  AppComponent.class.getName(), getClass().getName(), Application.class.getName());
          return mAppComponent;
      }
  
  
      private static class AppComponentCallbacks implements ComponentCallbacks2 {
          private Application mApplication;
          private AppComponent mAppComponent;
  
          public AppComponentCallbacks(Application application, AppComponent appComponent) {
              this.mApplication = application;
              this.mAppComponent = appComponent;
          }
  
          @Override
          public void onTrimMemory(int level) {
  
          }
  
          @Override
          public void onConfigurationChanged(Configuration newConfig) {
  
          }
  
          @Override
          public void onLowMemory() {
              //内存不足时清理图片请求框架的内存缓存
              mAppComponent.imageLoader().clear(mApplication, ImageConfigImpl
                      .builder()
                      .isClearMemory(true)
                      .build());
          }
      }
  
  }
  
  