package com.proxerme.library.api;

import com.proxerme.library.api.info.InfoApi;
import com.proxerme.library.api.notifications.NotificationsApi;
import com.proxerme.library.api.user.UserApi;
import com.proxerme.library.util.ProxerUrls;
import com.squareup.moshi.Moshi;
import okhttp3.OkHttpClient;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import retrofit2.Retrofit;
import retrofit2.converter.moshi.MoshiConverterFactory;

/**
 * TODO: Describe class
 *
 * @author Ruben Gees
 */
public final class ProxerApi {

    private final NotificationsApi notifications;
    private final UserApi user;
    private final InfoApi info;

    ProxerApi(@NotNull final Retrofit retrofit) {
        notifications = new NotificationsApi(retrofit);
        user = new UserApi(retrofit);
        info = new InfoApi(retrofit);
    }

    @NotNull
    public NotificationsApi notifications() {
        return notifications;
    }

    @NotNull
    public UserApi user() {
        return user;
    }

    @NotNull
    public InfoApi info() {
        return info;
    }

    public static class Builder {

        private static final String DEFAULT_USER_AGENT = "ProxerLibAndroid/3.0.0";

        private final String apiKey;
        private LoginTokenManager loginTokenManager;
        private String userAgent;

        private Moshi moshi;
        private OkHttpClient okHttp;
        private Retrofit retrofit;

        public Builder(@NotNull final String apiKey) {
            this.apiKey = apiKey;
        }

        @NotNull
        public Builder loginTokenManager(@NotNull final LoginTokenManager loginTokenManager) {
            this.loginTokenManager = loginTokenManager;

            return this;
        }

        @NotNull
        public Builder userAgent(@Nullable final String userAgent) {
            this.userAgent = userAgent;

            return this;
        }

        @NotNull
        public Builder moshi(@Nullable final Moshi moshi) {
            this.moshi = moshi;

            return this;
        }

        @NotNull
        public Builder okHttp(@Nullable final OkHttpClient okHttp) {
            this.okHttp = okHttp;

            return this;
        }

        @NotNull
        public Builder retrofit(@Nullable final Retrofit retrofit) {
            this.retrofit = retrofit;

            return this;
        }

        @NotNull
        public ProxerApi build() {
            initLoginTokenManager();
            initUserAgent();
            initMoshi();
            initOkHttp();
            initRetrofit();

            return new ProxerApi(retrofit);
        }

        private void initLoginTokenManager() {
            if (loginTokenManager == null) {
                loginTokenManager = new DefaultLoginTokenManager();
            }
        }

        private void initUserAgent() {
            if (userAgent == null) {
                userAgent = DEFAULT_USER_AGENT;
            }
        }

        private void initMoshi() {
            final Moshi.Builder builder;

            if (moshi == null) {
                builder = new Moshi.Builder();
            } else {
                builder = moshi.newBuilder();
            }

            moshi = builder
                    .add(new VoidAdapter())
                    .add(new TimestampDateAdapter())
                    .add(new FixRatingDetailsAdapter())
                    .build();
        }

        private void initOkHttp() {
            final OkHttpClient.Builder builder;

            if (okHttp == null) {
                builder = new OkHttpClient.Builder();
            } else {
                builder = okHttp.newBuilder();
            }

            okHttp = builder
                    .addInterceptor(new HeaderInterceptor(apiKey, userAgent))
                    .addInterceptor(new LoginTokenInterceptor(loginTokenManager))
                    .build();
        }

        private void initRetrofit() {
            final Retrofit.Builder builder;

            if (retrofit == null) {
                builder = new Retrofit.Builder();
            } else {
                builder = retrofit.newBuilder();
            }

            retrofit = builder.baseUrl(ProxerUrls.apiBase())
                    .client(okHttp)
                    .addCallAdapterFactory(new ProxerResponseCallAdapterFactory())
                    .addConverterFactory(MoshiConverterFactory.create(moshi))
                    .addConverterFactory(new EnumRetrofitConverterFactory())
                    .build();
        }
    }
}

@@ -262,16 +262,44 @@
 .Moshi;%0A
+import okhttp3.Interceptor;%0A
 import o
@@ -488,16 +488,40 @@
 ctory;%0A%0A
+import java.util.List;%0A%0A
 /**%0A * T
@@ -3737,24 +3737,79 @@
     
-okHttp = builder
+final List%3CInterceptor%3E existingInterceptors = builder.interceptors();%0A
 %0A   
@@ -3813,36 +3813,32 @@
             
-        .add
+existing
 Interceptor(
@@ -3832,25 +3832,33 @@
 gInterceptor
-(
+s.add(0, 
 new HeaderIn
@@ -3886,16 +3886,17 @@
 rAgent))
+;
 %0A       
@@ -3900,28 +3900,24 @@
         
-        .add
+existing
 Intercep
@@ -3919,17 +3919,25 @@
 erceptor
-(
+s.add(1, 
 new Logi
@@ -3973,21 +3973,19 @@
 anager))
-%0A    
+;%0A%0A
         
@@ -3980,36 +3980,48 @@
 );%0A%0A            
-    
+okHttp = builder
 .build();%0A      

Add our interceptors to the head of the list