package com.battlelancer.seriesguide.loaders;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import com.battlelancer.seriesguide.R;
import com.battlelancer.seriesguide.SgApp;
import com.battlelancer.seriesguide.enums.MoviesDiscoverLink;
import com.battlelancer.seriesguide.settings.DisplaySettings;
import com.battlelancer.seriesguide.tmdbapi.SgTmdb;
import com.uwetrottmann.androidutils.AndroidUtils;
import com.uwetrottmann.androidutils.GenericSimpleLoader;
import com.uwetrottmann.tmdb2.Tmdb;
import com.uwetrottmann.tmdb2.entities.DiscoverFilter;
import com.uwetrottmann.tmdb2.entities.Movie;
import com.uwetrottmann.tmdb2.entities.MovieResultsPage;
import com.uwetrottmann.tmdb2.entities.TmdbDate;
import com.uwetrottmann.tmdb2.enumerations.ReleaseType;
import com.uwetrottmann.tmdb2.services.MoviesService;
import com.uwetrottmann.tmdb2.services.SearchService;
import dagger.Lazy;
import java.io.IOException;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import javax.inject.Inject;
import retrofit2.Call;
import retrofit2.Response;
/**
* Loads a list of movies from TMDb.
*/
public class TmdbMoviesLoader extends GenericSimpleLoader<TmdbMoviesLoader.Result> {
public static class Result {
/** If loading failed, is null. Empty if no results. */
@Nullable public List<Movie> results;
@NonNull public String emptyText;
public Result(@Nullable List<Movie> results, @NonNull String emptyText) {
this.results = results;
this.emptyText = emptyText;
}
}
@Inject Lazy<Tmdb> tmdb;
@Inject Lazy<MoviesService> moviesService;
@Inject Lazy<SearchService> searchService;
@NonNull private final MoviesDiscoverLink link;
@Nullable private String query;
/**
* If a query is given, will load search results for that query. Otherwise will load a list of
* movies based on the given link.
*/
public TmdbMoviesLoader(SgApp app, @NonNull MoviesDiscoverLink link, @Nullable String query) {
super(app);
app.getServicesComponent().inject(this);
this.link = link;
this.query = query;
}
@Override
public Result loadInBackground() {
String languageCode = DisplaySettings.getMoviesLanguage(getContext());
String regionCode = DisplaySettings.getMoviesRegion(getContext());
List<Movie> results = null;
String action = null;
try {
Response<MovieResultsPage> response;
if (TextUtils.isEmpty(query)) {
MoviesService moviesService = this.moviesService.get();
Call<MovieResultsPage> call;
switch (link) {
case POPULAR:
action = "get popular movies";
call = moviesService.popular(null, languageCode);
break;
case DIGITAL:
action = "get movie digital releases";
call = tmdb.get().discoverMovie()
.with_release_type(new DiscoverFilter(DiscoverFilter.Separator.AND,
ReleaseType.DIGITAL))
.release_date_lte(getDateNow())
.release_date_gte(getDateOneMonthAgo())
.language(languageCode)
.region(regionCode)
.build();
break;
case DISC:
action = "get movie disc releases";
call = tmdb.get().discoverMovie()
.with_release_type(new DiscoverFilter(DiscoverFilter.Separator.AND,
ReleaseType.PHYSICAL))
.release_date_lte(getDateNow())
.release_date_gte(getDateOneMonthAgo())
.language(languageCode)
.region(regionCode)
.build();
break;
case IN_THEATERS:
default:
action = "get now playing movies";
call = tmdb.get().discoverMovie()
.with_release_type(new DiscoverFilter(DiscoverFilter.Separator.OR,
ReleaseType.THEATRICAL, ReleaseType.THEATRICAL_LIMITED))
.release_date_lte(getDateNow())
.release_date_gte(getDateOneMonthAgo())
.language(languageCode)
.region(regionCode)
.build();
break;
}
response = call.execute();
} else {
action = "search for movies";
response = searchService.get()
.movie(query, null, languageCode, false, null, null, null)
.execute();
}
if (response.isSuccessful()) {
MovieResultsPage page = response.body();
if (page != null) {
results = page.results;
}
} else {
SgTmdb.trackFailedRequest(getContext(), action, response);
return buildErrorResult();
}
} catch (IOException e) {
SgTmdb.trackFailedRequest(getContext(), action, e);
// only check for connection here to allow hitting the response cache
return AndroidUtils.isNetworkConnected(getContext())
? buildErrorResult()
: new Result(null, getContext().getString(R.string.offline));
}
return new Result(results, getContext().getString(R.string.no_results));
}
private TmdbDate getDateNow() {
return new TmdbDate(new Date());
}
private TmdbDate getDateOneMonthAgo() {
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.DAY_OF_MONTH, -30);
return new TmdbDate(calendar.getTime());
}
private Result buildErrorResult() {
return new Result(null, getContext().getString(R.string.api_error_generic,
getContext().getString(R.string.tmdb)));
}
}