package co.smartreceipts.android.identity;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import com.google.common.base.Preconditions;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import co.smartreceipts.android.apis.ApiValidationException;
import co.smartreceipts.android.apis.hosts.ServiceManager;
import co.smartreceipts.android.identity.apis.organizations.Organization;
import co.smartreceipts.android.identity.apis.organizations.OrganizationsResponse;
import co.smartreceipts.android.identity.apis.organizations.OrganizationsService;
import co.smartreceipts.android.identity.store.IdentityStore;
import co.smartreceipts.android.settings.UserPreferenceManager;
import co.smartreceipts.android.settings.catalog.UserPreference;
import co.smartreceipts.android.utils.FeatureFlags;
import co.smartreceipts.android.utils.log.Logger;
import io.reactivex.Observable;
public class OrganizationManager {
private final ServiceManager serviceManager;
private final IdentityStore identityStore;
private final UserPreferenceManager userPreferenceManager;
public OrganizationManager(@NonNull ServiceManager serviceManager, @NonNull IdentityStore identityStore, @NonNull UserPreferenceManager userPreferenceManager) {
this.serviceManager = Preconditions.checkNotNull(serviceManager);
this.identityStore = Preconditions.checkNotNull(identityStore);
this.userPreferenceManager = Preconditions.checkNotNull(userPreferenceManager);
}
@NonNull
public Observable<OrganizationsResponse> getOrganizations() {
if (FeatureFlags.OrganizationSyncing.isEnabled()) {
return getOrganizationsApiRequest()
.flatMap(organizationsResponse -> applyOrganizationsResponse(organizationsResponse)
.map(o -> organizationsResponse))
.doOnError(throwable -> {
Logger.error(this, "Failed to complete the organizations request", throwable);
});
} else {
return Observable.just(new OrganizationsResponse(null));
}
}
@NonNull
private Observable<OrganizationsResponse> getOrganizationsApiRequest() {
if (identityStore.isLoggedIn()) {
return serviceManager.getService(OrganizationsService.class).organizations();
} else {
return Observable.error(new IllegalStateException("Cannot fetch the user's organizations until we're logged in"));
}
}
@NonNull
private Observable<Object> applyOrganizationsResponse(@NonNull final OrganizationsResponse response) {
return getPrimaryOrganization(response)
.flatMap(organization -> getOrganizationSettings(organization)
.flatMap(settings -> userPreferenceManager.getUserPreferencesObservable()
.flatMapIterable(userPreferences -> userPreferences)
.flatMap(userPreference -> apply(settings, userPreference))));
}
@NonNull
private Observable<Organization> getPrimaryOrganization(@NonNull final OrganizationsResponse response) {
return Observable.create(emitter -> {
if (response.getOrganizations() != null && !response.getOrganizations().isEmpty()) {
final Organization organization = response.getOrganizations().get(0);
if (organization.getError() != null && organization.getError().hasError()) {
emitter.onError(new ApiValidationException(TextUtils.join(", ", organization.getError().getErrors())));
} else {
emitter.onNext(organization);
emitter.onComplete();
}
} else {
emitter.onComplete();
}
});
}
@NonNull
private Observable<JsonObject> getOrganizationSettings(@NonNull final Organization organization) {
return Observable.create(emitter -> {
if (organization.getAppSettings() != null && organization.getAppSettings().getSettings() != null) {
emitter.onNext(organization.getAppSettings().getSettings());
}
emitter.onComplete();
});
}
@Nullable
@SuppressWarnings("unchecked")
public <T> Observable<T> apply(@NonNull JsonObject settings, @NonNull UserPreference<T> toPreference) {
final String preferenceName = userPreferenceManager.getName(toPreference);
if (settings.has(preferenceName)) {
final JsonElement element = settings.get(preferenceName);
if (!element.isJsonNull()) {
Logger.debug(OrganizationManager.this, "Giving preference \'{}\' a value of {}.", preferenceName, element);
if (Boolean.class.equals(toPreference.getType())) {
return userPreferenceManager.setObservable(toPreference, (T) Boolean.valueOf(element.getAsBoolean()));
} else if (String.class.equals(toPreference.getType())) {
return userPreferenceManager.setObservable(toPreference, (T) element.getAsString());
} else if (Float.class.equals(toPreference.getType())) {
return userPreferenceManager.setObservable(toPreference, (T) Float.valueOf(element.getAsFloat()));
} else if (Integer.class.equals(toPreference.getType())) {
return userPreferenceManager.setObservable(toPreference, (T) Integer.valueOf(element.getAsInt()));
} else {
return Observable.error(new Exception("Unsupported organization setting type for " + preferenceName));
}
} else {
Logger.debug(OrganizationManager.this, "Skipping preference \'{}\', which is defined as null.", preferenceName, element);
return Observable.empty();
}
} else {
Logger.warn(OrganizationManager.this, "Failed to find preference: {}", preferenceName);
return Observable.empty();
}
}
}