package com.github.ayltai.newspaper;

import javax.inject.Inject;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatDelegate;
import android.widget.TextView;

import com.google.android.gms.appinvite.AppInvite;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.firebase.remoteconfig.FirebaseRemoteConfig;

import com.github.ayltai.newspaper.client.ClientFactory;
import com.github.ayltai.newspaper.graphics.FaceDetectorFactory;
import com.github.ayltai.newspaper.graphics.FrescoImageLoader;
import com.github.ayltai.newspaper.net.ConnectivityChangeReceiver;
import com.github.ayltai.newspaper.setting.Settings;
import com.github.ayltai.newspaper.util.ContextUtils;
import com.github.ayltai.newspaper.util.LogUtils;
import com.github.ayltai.newspaper.util.TestUtils;
import com.github.piasy.biv.BigImageViewer;

import io.reactivex.Single;
import io.reactivex.schedulers.Schedulers;

public final class MainActivity extends BaseActivity implements GoogleApiClient.OnConnectionFailedListener {
    //region Variables

    @Inject
    FlowController controller;

    private FirebaseRemoteConfig       config;
    private GoogleApiClient            client;
    private ConnectivityChangeReceiver receiver;
    private Snackbar                   snackbar;

    private boolean rememberPosition;

    //endregion

    static {
        AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
    }

    @Inject
    public MainActivity() {
    }

    @Override
    protected void onCreate(@Nullable final Bundle savedInstanceState) {
        ContextUtils.setAppTheme(this);

        FrescoImageLoader.initialize(this.getCacheDir().getAbsolutePath());
        BigImageViewer.initialize(FrescoImageLoader.getInstance());

        super.onCreate(savedInstanceState);

        if (!TestUtils.isRunningInstrumentedTest()) {
            this.setUpRemoteConfig();

            this.client = new GoogleApiClient.Builder(this.getApplicationContext())
                .enableAutoManage(this, this)
                .addApiIfAvailable(AppInvite.API)
                .build();
        }

        this.setUpConnectivityChangeReceiver();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        if (!this.rememberPosition) Settings.resetPosition();

        this.controller.onDestroy();
        this.controller = null;

        // Releases resources only if the app really quits
        // The app instances lifecycle may overlap when the app restarts
        if (this.isFinishing()) {
            RxBus.getInstance().unregisterAll();
            FrescoImageLoader.shutDown();
            FaceDetectorFactory.release();
            ClientFactory.getInstance(this).close();
        }
    }

    @Override
    protected void attachBaseContext(final Context newBase) {
        DaggerMainComponent.builder()
            .mainModule(new MainModule(this))
            .build()
            .inject(this);

        super.attachBaseContext(this.controller.attachNewBase(newBase));
    }

    @Override
    protected void onResume() {
        super.onResume();

        this.receiver.register();
    }

    @Override
    protected void onPause() {
        super.onPause();

        this.receiver.unregister();
    }

    @Override
    public void onStart() {
        super.onStart();

        if (!TestUtils.isRunningInstrumentedTest()) this.client.connect();
    }

    @Override
    public void onStop() {
        super.onStop();

        if (!TestUtils.isRunningInstrumentedTest()) this.client.disconnect();
    }

    @Override
    protected void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (requestCode == Constants.REQUEST_SETTINGS && resultCode == Activity.RESULT_OK) {
            this.rememberPosition = true;

            this.finish();
            this.startActivity(this.getBaseContext().getPackageManager().getLaunchIntentForPackage(this.getBaseContext().getPackageName()).addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP));
        }
    }

    @Override
    public void onBackPressed() {
        if (!this.controller.onBackPressed()) super.onBackPressed();
    }

    @Override
    public void onConnectionFailed(@NonNull final ConnectionResult connectionResult) {
        if (connectionResult.hasResolution()) {
            try {
                connectionResult.startResolutionForResult(this, Constants.REQUEST_FIREBASE);
            } catch (final IntentSender.SendIntentException e) {
                MainActivity.logConnectionError(connectionResult);
            }
        } else {
            MainActivity.logConnectionError(connectionResult);
        }
    }

    private void setUpConnectivityChangeReceiver() {
        this.snackbar = Snackbar.make(this.findViewById(android.R.id.content), R.string.error_no_connection, Snackbar.LENGTH_INDEFINITE);
        ((TextView)this.snackbar.getView().findViewById(android.support.design.R.id.snackbar_text)).setTextColor(ContextUtils.getColor(this, R.attr.textColorInverse));

        this.receiver = new ConnectivityChangeReceiver(this) {
            @Override
            protected void onConnectivityChange(final boolean isConnected) {
                if (isConnected) {
                    if (MainActivity.this.snackbar.isShown()) MainActivity.this.snackbar.dismiss();
                } else {
                    if (!MainActivity.this.snackbar.isShown()) MainActivity.this.snackbar.show();
                }
            }
        };
    }

    private void setUpRemoteConfig() {
        Single.<FirebaseRemoteConfig>create(emitter -> emitter.onSuccess(FirebaseRemoteConfig.getInstance()))
            .observeOn(Schedulers.io())
            .subscribeOn(Schedulers.io())
            .subscribe(config -> {
                this.config = config;
                this.config.setDefaults(R.xml.config);

                this.applyRemoteConfig();

                this.config.fetch(Constants.REMOTE_CONFIG_CACHE_EXPIRATION)
                    .addOnCompleteListener(task -> {
                        if (task.isSuccessful()) {
                            this.config.activateFetched();
                        } else {
                            LogUtils.getInstance().w(this.getClass().getSimpleName(), "Failed to fetch remote config");
                        }
                    });
            });
    }

    private void applyRemoteConfig() {
        Configs.apply(this.config);
    }

    private static void logConnectionError(@NonNull final ConnectionResult connectionResult) {
        LogUtils.getInstance().w(MainActivity.class.getName(), "onConnectionFailed: errorCode=" + connectionResult.getErrorCode() + ", errorMessage=" + connectionResult.getErrorMessage());
    }
}

@@ -171,97 +171,17 @@
 oid.
-content.IntentSender;%0Aimport android.os.Bundle;%0Aimport android.support.annotation.NonNull
+os.Bundle
 ;%0Aim
@@ -355,172 +355,8 @@
 w;%0A%0A
-import com.google.android.gms.appinvite.AppInvite;%0Aimport com.google.android.gms.common.ConnectionResult;%0Aimport com.google.android.gms.common.api.GoogleApiClient;%0A
 impo
@@ -1048,62 +1048,8 @@
 ity 
-implements GoogleApiClient.OnConnectionFailedListener 
 %7B%0A  
@@ -1165,55 +1165,8 @@
 ig;%0A
-    private GoogleApiClient            client;%0A
     
@@ -1821,30 +1821,16 @@
 dTest())
- %7B%0A           
  this.se
@@ -1853,225 +1853,8 @@
 );%0A%0A
-            this.client = new GoogleApiClient.Builder(this.getApplicationContext())%0A                .enableAutoManage(this, this)%0A                .addApiIfAvailable(AppInvite.API)%0A                .build();%0A        %7D%0A%0A
     
@@ -3003,309 +3003,8 @@
  %7D%0A%0A
-    @Override%0A    public void onStart() %7B%0A        super.onStart();%0A%0A        if (!TestUtils.isRunningInstrumentedTest()) this.client.connect();%0A    %7D%0A%0A    @Override%0A    public void onStop() %7B%0A        super.onStop();%0A%0A        if (!TestUtils.isRunningInstrumentedTest()) this.client.disconnect();%0A    %7D%0A%0A
     
@@ -3669,511 +3669,8 @@
  %7D%0A%0A
-    @Override%0A    public void onConnectionFailed(@NonNull final ConnectionResult connectionResult) %7B%0A        if (connectionResult.hasResolution()) %7B%0A            try %7B%0A                connectionResult.startResolutionForResult(this, Constants.REQUEST_FIREBASE);%0A            %7D catch (final IntentSender.SendIntentException e) %7B%0A                MainActivity.logConnectionError(connectionResult);%0A            %7D%0A        %7D else %7B%0A            MainActivity.logConnectionError(connectionResult);%0A        %7D%0A    %7D%0A%0A
     
@@ -5394,32 +5394,32 @@
 emoteConfig() %7B%0A
+
         Configs.
@@ -5447,298 +5447,7 @@
    %7D
-%0A%0A    private static void logConnectionError(@NonNull final ConnectionResult connectionResult) %7B%0A        LogUtils.getInstance().w(MainActivity.class.getName(), %22onConnectionFailed: errorCode=%22 + connectionResult.getErrorCode() + %22, errorMessage=%22 + connectionResult.getErrorMessage());%0A    %7D
 %0A%7D%0A

Remove Firebase AppInvite