package org.wikipedia.nearby;
import android.support.annotation.NonNull;
import android.support.annotation.VisibleForTesting;
import org.wikipedia.Constants;
import org.wikipedia.dataclient.WikiSite;
import org.wikipedia.dataclient.mwapi.MwException;
import org.wikipedia.dataclient.mwapi.MwQueryResponse;
import org.wikipedia.dataclient.retrofit.MwCachedService;
import org.wikipedia.dataclient.retrofit.WikiCachedService;
import java.util.ArrayList;
import java.util.Locale;
import retrofit2.Call;
import retrofit2.Response;
import retrofit2.http.GET;
import retrofit2.http.Query;
class NearbyClient {
public interface Callback {
void success(@NonNull Call<MwQueryResponse<Nearby>> call, @NonNull NearbyResult result);
void failure(@NonNull Call<MwQueryResponse<Nearby>> call, @NonNull Throwable caught);
}
private static final int MAX_RADIUS = 10_000;
@NonNull private final WikiCachedService<Service> cachedService = new MwCachedService<>(Service.class);
public Call<MwQueryResponse<Nearby>> request(@NonNull WikiSite wiki, double latitude,
double longitude, double radius,
@NonNull Callback cb) {
return request(wiki, cachedService.service(wiki), latitude, longitude, radius, cb);
}
@VisibleForTesting Call<MwQueryResponse<Nearby>> request(@NonNull final WikiSite wiki,
@NonNull Service service,
double latitude, double longitude,
double radius,
@NonNull final Callback cb) {
String latLng = String.format(Locale.ROOT, "%f|%f", latitude, longitude);
radius = Math.min(MAX_RADIUS, radius);
Call<MwQueryResponse<Nearby>> call
= service.request(latLng, radius, Constants.PREFERRED_THUMB_SIZE);
call.enqueue(new retrofit2.Callback<MwQueryResponse<Nearby>>() {
@Override
public void onResponse(Call<MwQueryResponse<Nearby>> call,
Response<MwQueryResponse<Nearby>> response) {
// The API results here are unusual in that, if there are no valid results, the
// response won't even have a "query" key. Nor will we receive an error.
// Accordingly, let's assume that we just got an empty result set unless the
// API explicitly tells us we have an error.
if (response.body().success()) {
cb.success(call, new NearbyResult(wiki, response.body().query().list()));
} else if (response.body().hasError()) {
cb.failure(call, new MwException(response.body().getError()));
} else {
cb.success(call, new NearbyResult(wiki, new ArrayList<NearbyPage>()));
}
}
@Override
public void onFailure(Call<MwQueryResponse<Nearby>> call, Throwable t) {
cb.failure(call, t);
}
});
return call;
}
@VisibleForTesting interface Service {
@GET("w/api.php?action=query&format=json&formatversion=2&prop=coordinates|pageimages|pageterms"
+ "&colimit=50&piprop=thumbnail&pilicense=any&pilimit=50&wbptterms=description"
+ "&generator=geosearch&ggslimit=50&continue=")
Call<MwQueryResponse<Nearby>> request(@NonNull @Query("ggscoord") String coord,
@Query("ggsradius") double radius,
@Query("pithumbsize") int thumbsize);
}
}