package com.kickstarter.ui.intentmappers;
import android.content.Intent;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import com.kickstarter.libs.rx.transformers.Transformers;
import com.kickstarter.libs.utils.ObjectUtils;
import com.kickstarter.models.Category;
import com.kickstarter.models.Location;
import com.kickstarter.services.ApiClientType;
import com.kickstarter.services.DiscoveryParams;
import com.kickstarter.ui.IntentKey;
import java.util.ArrayList;
import java.util.List;
import rx.Observable;
public final class DiscoveryIntentMapper {
private DiscoveryIntentMapper() {}
public static Observable<DiscoveryParams> params(final @NonNull Intent intent,
final @NonNull ApiClientType client) {
final Observable<DiscoveryParams> paramsFromParcel = Observable.just(paramsFromIntent(intent))
.filter(ObjectUtils::isNotNull);
final Observable<DiscoveryParams> paramsFromUri = Observable.just(IntentMapper.uri(intent))
.filter(ObjectUtils::isNotNull)
.map(DiscoveryParams::fromUri)
.flatMap(uri -> paramsFromUri(uri, client));
return Observable.merge(paramsFromParcel, paramsFromUri);
}
private static @Nullable DiscoveryParams paramsFromIntent(final @NonNull Intent intent) {
return intent.getParcelableExtra(IntentKey.DISCOVERY_PARAMS);
}
/**
* Returns params where category and location params have been converted into {@link Category}
* and {@link Location} objects.
*/
private static @NonNull Observable<DiscoveryParams> paramsFromUri(final @NonNull DiscoveryParams params,
final @NonNull ApiClientType client) {
return Observable.zip(paramBuilders(params, client), builders -> {
DiscoveryParams.Builder builder = DiscoveryParams.builder();
for (final Object object : builders) {
final DiscoveryParams.Builder b = (DiscoveryParams.Builder) object;
builder = builder.mergeWith(b);
}
return builder.build();
});
}
/**
* Creates observables that will perform API requests to retrieve additional data needed to fill out
* a full discovery params object. For example, if `params` holds only a category slug and no actual
* category data, we will perform a request to get the full category from the API.
* @param params The discovery params that is potentially missing full data.
* @return A list of observables, each responsible for retrieving more data from the API. The
* observables emit *builders* of params, and hence can later be merged into a single params object.
*/
private static @NonNull List<Observable<DiscoveryParams.Builder>> paramBuilders(final @NonNull DiscoveryParams params,
final @NonNull ApiClientType client) {
final List<Observable<DiscoveryParams.Builder>> paramBuilders = new ArrayList<>();
final String categoryParam = params.categoryParam();
if (categoryParam != null) {
paramBuilders.add(
client
.fetchCategory(categoryParam)
.map(c -> DiscoveryParams.builder().category(c))
.compose(Transformers.neverError())
);
}
final String locationParam = params.locationParam();
if (locationParam != null) {
paramBuilders.add(
client
.fetchLocation(locationParam)
.map(l -> DiscoveryParams.builder().location(l))
.compose(Transformers.neverError())
);
}
paramBuilders.add(Observable.just(params.toBuilder()));
return paramBuilders;
}
}