package com.mirhoseini.marvel.domain;
import com.mirhoseini.marvel.util.StateManager;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import javax.inject.Named;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
import okhttp3.Cache;
import okhttp3.CacheControl;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;
/**
* Created by Mohsen on 20/10/2016.
*/
@Module
public class ClientModule {
private static final String HTTP_CACHE_PATH = "http-cache";
private static final String CACHE_CONTROL = "Cache-Control";
private static final String PRAGMA = "Pragma";
@Singleton
@Provides
public OkHttpClient provideOkHttpClient(HttpLoggingInterceptor loggingInterceptor,
@Named("networkTimeoutInSeconds") int networkTimeoutInSeconds,
@Named("isDebug") boolean isDebug,
Cache cache,
@Named("cacheInterceptor") Interceptor cacheInterceptor,
@Named("offlineInterceptor") Interceptor offlineCacheInterceptor,
@Named("retryInterceptor") Interceptor retryInterceptor) {
OkHttpClient.Builder okHttpClient = new OkHttpClient.Builder()
.addNetworkInterceptor(cacheInterceptor)
.addInterceptor(offlineCacheInterceptor)
.addInterceptor(retryInterceptor)
.cache(cache)
.connectTimeout(networkTimeoutInSeconds, TimeUnit.SECONDS);
//show logs if app is in Debug mode
if (isDebug)
okHttpClient.addInterceptor(loggingInterceptor);
return okHttpClient.build();
}
@Singleton
@Provides
public HttpLoggingInterceptor provideHttpLoggingInterceptor() {
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
return logging;
}
@Provides
@Singleton
public Cache provideCache(@Named("cacheDir") File cacheDir, @Named("cacheSize") long cacheSize) {
Cache cache = null;
try {
cache = new Cache(new File(cacheDir.getPath(), HTTP_CACHE_PATH), cacheSize);
} catch (Exception e) {
e.printStackTrace();
}
return cache;
}
@Singleton
@Provides
@Named("cacheInterceptor")
public Interceptor provideCacheInterceptor(@Named("cacheMaxAge") int maxAgeMin) {
return chain -> {
Response response = chain.proceed(chain.request());
CacheControl cacheControl = new CacheControl.Builder()
.maxAge(maxAgeMin, TimeUnit.MINUTES)
.build();
return response.newBuilder()
.removeHeader(PRAGMA)
.removeHeader(CACHE_CONTROL)
.header(CACHE_CONTROL, cacheControl.toString())
.build();
};
}
@Singleton
@Provides
@Named("offlineInterceptor")
public Interceptor provideOfflineCacheInterceptor(StateManager stateManager, @Named("cacheMaxStale") int maxStaleDay) {
return chain -> {
Request request = chain.request();
if (!stateManager.isConnect()) {
CacheControl cacheControl = new CacheControl.Builder()
.maxStale(maxStaleDay, TimeUnit.DAYS)
.build();
request = request.newBuilder()
.cacheControl(cacheControl)
.build();
}
return chain.proceed(request);
};
}
@Singleton
@Provides
@Named("retryInterceptor")
public Interceptor provideRetryInterceptor(@Named("retryCount") int retryCount) {
return chain -> {
Request request = chain.request();
Response response = null;
IOException exception = null;
int tryCount = 0;
while (tryCount < retryCount && (null == response || !response.isSuccessful())) {
// retry the request
try {
response = chain.proceed(request);
} catch (IOException e) {
exception = e;
} finally {
tryCount++;
}
}
// throw last exception
if (null == response && null != exception)
throw exception;
// otherwise just pass the original response on
return response;
};
}
}