package com.kickstarter.libs;
import android.content.res.AssetManager;
import android.support.annotation.NonNull;
import com.google.gson.Gson;
import com.kickstarter.libs.preferences.StringPreferenceType;
import com.kickstarter.libs.rx.transformers.Transformers;
import com.kickstarter.libs.utils.ObjectUtils;
import java.io.IOException;
import java.io.InputStream;
import rx.Observable;
import rx.android.schedulers.AndroidSchedulers;
import rx.subjects.BehaviorSubject;
import timber.log.Timber;
public final class CurrentConfig implements CurrentConfigType {
private final static String ASSET_PATH = "json/server-config.json";
private final BehaviorSubject<Config> config = BehaviorSubject.create();
public CurrentConfig(final @NonNull AssetManager assetManager,
final @NonNull Gson gson,
final @NonNull StringPreferenceType configPreference) {
// Loads config from disk
final Observable<Config> diskConfig = Observable.just(ASSET_PATH)
.map(path -> configJSONString(path, assetManager))
.map(json -> gson.fromJson(json, Config.class))
.filter(ObjectUtils::isNotNull)
.compose(Transformers.neverError())
.subscribeOn(AndroidSchedulers.mainThread());
// Loads config from string preference
final Observable<Config> prefConfig = Observable.just(configPreference)
.map(StringPreferenceType::get)
.map(json -> gson.fromJson(json, Config.class))
.filter(ObjectUtils::isNotNull)
.compose(Transformers.neverError())
.subscribeOn(AndroidSchedulers.mainThread());
// Seed config observable with what's cached
Observable.concat(prefConfig, diskConfig)
.take(1)
.subscribe(this.config::onNext);
// Cache any new values to preferences
this.config.skip(1)
.filter(ObjectUtils::isNotNull)
.subscribe(config -> configPreference.set(gson.toJson(config, Config.class)));
}
/**
* Get an observable representation of the current config. Emits immediately with the freshes copy of the config
* and then emits again for any fresher values.
*/
public @NonNull Observable<Config> observable() {
return this.config;
}
/**
* @return The most recent config.
*/
public @NonNull Config getConfig() {
return this.config.getValue();
}
public void config(final @NonNull Config config) {
this.config.onNext(config);
}
/**
* @param assetPath Path where `server-config.json` lives.
* @param assetManager Asset manager to use to load `server-config.json`.
* @return A string representation of the config JSON.
*/
private @NonNull String configJSONString(final @NonNull String assetPath, final @NonNull AssetManager assetManager) {
try {
final InputStream input;
input = assetManager.open(assetPath);
final byte[] buffer = new byte[input.available()];
input.read(buffer);
input.close();
return new String(buffer);
} catch (final IOException e) {
Timber.e(e.getMessage());
// TODO: This should probably be fatal?
}
return "{}";
}
}