package com.lukekorth.photo_paper;

import android.app.Application;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;

import com.google.gson.GsonBuilder;
import com.lukekorth.fivehundredpx.AccessToken;
import com.lukekorth.mailable_log.MailableLog;
import com.lukekorth.photo_paper.api.FiveHundredPxClient;
import com.lukekorth.photo_paper.helpers.ConsumerApiKeyInterceptor;
import com.lukekorth.photo_paper.helpers.ThreadBus;
import com.lukekorth.photo_paper.helpers.UserAgentInterceptor;
import com.lukekorth.photo_paper.models.User;
import com.lukekorth.photo_paper.models.UserUpdatedEvent;
import com.squareup.otto.Bus;
import com.squareup.otto.Subscribe;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Date;

import io.realm.Realm;
import io.realm.RealmConfiguration;
import okhttp3.OkHttpClient;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
import se.akerfeldt.okhttp.signpost.OkHttpOAuthConsumer;
import se.akerfeldt.okhttp.signpost.SigningInterceptor;

public class WallpaperApplication extends Application implements Thread.UncaughtExceptionHandler {

    private static final String VERSION = "version";

    private Thread.UncaughtExceptionHandler mDefaultExceptionHandler;

    private static FiveHundredPxClient sApiClient;
    private static FiveHundredPxClient sNonLoggedInApiClient;
    private static ThreadBus sBus;

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

        migrate();
        MailableLog.init(this, BuildConfig.DEBUG);
        mDefaultExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
        Thread.setDefaultUncaughtExceptionHandler(this);
        DebugUtils.setup(this);

        Realm.init(this);
        RealmConfiguration realmConfiguration = new RealmConfiguration.Builder().build();
        Realm.setDefaultConfiguration(realmConfiguration);

        getBus().register(this);
    }

    private void migrate() {
        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
        SharedPreferences.Editor editor = prefs.edit();
        int version = prefs.getInt(VERSION, 0);
        if (BuildConfig.VERSION_CODE > version) {
            String now = new Date().toString();
            if (version == 0) {
                editor.putString("install_date", now);
            }

            editor.putString("upgrade_date", now);
            editor.putInt(VERSION, BuildConfig.VERSION_CODE);
            editor.apply();

            MailableLog.clearLog(this);
        }
    }

    @Override
    public void uncaughtException(Thread thread, Throwable ex) {
        Logger logger = LoggerFactory.getLogger("Exception");

        logger.error("thread.toString(): " + thread.toString());
        logger.error("Exception: " + ex.toString());
        logger.error("Exception stacktrace:");
        for (StackTraceElement trace : ex.getStackTrace()) {
            logger.error(trace.toString());
        }

        logger.error("");

        logger.error("cause.toString(): " + ex.getCause().toString());
        logger.error("Cause: " + ex.getCause().toString());
        logger.error("Cause stacktrace:");
        for (StackTraceElement trace : ex.getCause().getStackTrace()) {
            logger.error(trace.toString());
        }

        mDefaultExceptionHandler.uncaughtException(thread, ex);
    }

    @Subscribe
    public void onUserUpdated(UserUpdatedEvent event) {
        sApiClient = null;
    }

    public static FiveHundredPxClient getApiClient() {
        if (sApiClient == null) {
            Realm realm = Realm.getDefaultInstance();
            OkHttpClient.Builder okHttpBuilder = new OkHttpClient.Builder();
            if (User.isUserLoggedIn(realm)) {
                AccessToken accessToken = User.getLoggedInUserAccessToken(realm);
                OkHttpOAuthConsumer consumer = new OkHttpOAuthConsumer(BuildConfig.CONSUMER_KEY,
                        BuildConfig.CONSUMER_SECRET);
                consumer.setTokenWithSecret(accessToken.getToken(), accessToken.getTokenSecret());
                okHttpBuilder.addInterceptor(new SigningInterceptor(consumer));
            } else {
                okHttpBuilder.addInterceptor(new ConsumerApiKeyInterceptor());
            }

            okHttpBuilder.addInterceptor(new UserAgentInterceptor());

            if (BuildConfig.DEBUG) {
                okHttpBuilder.addNetworkInterceptor(DebugUtils.getDebugNetworkInterceptor());
            }

            sApiClient = new Retrofit.Builder()
                    .baseUrl("https://api.500px.com/v1/")
                    .addConverterFactory(GsonConverterFactory.create(new GsonBuilder()
                            .excludeFieldsWithoutExposeAnnotation()
                            .create()))
                    .client(okHttpBuilder.build())
                    .addConverterFactory(GsonConverterFactory.create())
                    .build()
                    .create(FiveHundredPxClient.class);

            realm.close();
        }

        return sApiClient;
    }

    public static FiveHundredPxClient getNonLoggedInApiClient() {
        if (sNonLoggedInApiClient == null) {
            OkHttpClient.Builder okHttpBuilder = new OkHttpClient.Builder()
                    .addInterceptor(new ConsumerApiKeyInterceptor())
                    .addInterceptor(new UserAgentInterceptor());

            if (BuildConfig.DEBUG) {
                okHttpBuilder.addNetworkInterceptor(DebugUtils.getDebugNetworkInterceptor());
            }

            sNonLoggedInApiClient = new Retrofit.Builder()
                    .baseUrl("https://api.500px.com/v1/")
                    .addConverterFactory(GsonConverterFactory.create(new GsonBuilder()
                            .excludeFieldsWithoutExposeAnnotation()
                            .create()))
                    .client(okHttpBuilder.build())
                    .addConverterFactory(GsonConverterFactory.create())
                    .build()
                    .create(FiveHundredPxClient.class);
        }

        return sNonLoggedInApiClient;
    }

    public static Bus getBus() {
        if (sBus == null) {
            sBus = new ThreadBus();
        }
        return sBus;
    }
}


@@ -696,66 +696,8 @@
 e;%0A%0A
-import org.slf4j.Logger;%0Aimport org.slf4j.LoggerFactory;%0A%0A
 impo
@@ -1057,51 +1057,8 @@
 ion 
-implements Thread.UncaughtExceptionHandler 
 %7B%0A%0A 
@@ -1114,79 +1114,8 @@
 %22;%0A%0A
-    private Thread.UncaughtExceptionHandler mDefaultExceptionHandler;%0A%0A
     
@@ -1403,145 +1403,8 @@
 G);%0A
-        mDefaultExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();%0A        Thread.setDefaultUncaughtExceptionHandler(this);%0A
     
@@ -2271,830 +2271,8 @@
  %7D%0A%0A
-    @Override%0A    public void uncaughtException(Thread thread, Throwable ex) %7B%0A        Logger logger = LoggerFactory.getLogger(%22Exception%22);%0A%0A        logger.error(%22thread.toString(): %22 + thread.toString());%0A        logger.error(%22Exception: %22 + ex.toString());%0A        logger.error(%22Exception stacktrace:%22);%0A        for (StackTraceElement trace : ex.getStackTrace()) %7B%0A            logger.error(trace.toString());%0A        %7D%0A%0A        logger.error(%22%22);%0A%0A        logger.error(%22cause.toString(): %22 + ex.getCause().toString());%0A        logger.error(%22Cause: %22 + ex.getCause().toString());%0A        logger.error(%22Cause stacktrace:%22);%0A        for (StackTraceElement trace : ex.getCause().getStackTrace()) %7B%0A            logger.error(trace.toString());%0A        %7D%0A%0A        mDefaultExceptionHandler.uncaughtException(thread, ex);%0A    %7D%0A%0A
     

Remove exception logging in favor of Firebase crash reporting