/*
* This file is part of Popcorn Time.
*
* Popcorn Time is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Popcorn Time is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Popcorn Time. If not, see <http://www.gnu.org/licenses/>.
*/
package pct.droid.tv.service;
import android.app.IntentService;
import android.app.PendingIntent;
import android.app.TaskStackBuilder;
import android.content.Intent;
import android.support.annotation.NonNull;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicBoolean;
import pct.droid.base.providers.media.EZTVProvider;
import pct.droid.base.providers.media.MediaProvider;
import pct.droid.base.providers.media.YTSProvider;
import pct.droid.base.providers.media.models.Episode;
import pct.droid.base.providers.media.models.Media;
import pct.droid.base.providers.media.models.Movie;
import pct.droid.base.providers.media.models.Show;
import pct.droid.base.utils.VersionUtils;
import pct.droid.tv.R;
import pct.droid.tv.activities.PTVMediaDetailActivity;
import pct.droid.tv.service.recommendation.RecommendationBuilder;
import pct.droid.tv.service.recommendation.RecommendationContentProvider;
import timber.log.Timber;
public class RecommendationService extends IntentService {
private ArrayList<Media> mMovies = new ArrayList<>();
private ArrayList<Media> mShows = new ArrayList<>();
public RecommendationService() {
super("RecommendationService");
}
private static final int MAX_MOVIE_RECOMMENDATIONS = 3;
private static final int MAX_SHOW_RECOMMENDATIONS = 3;
private EZTVProvider mShowProvider = new EZTVProvider();
private YTSProvider mMovieProvider = new YTSProvider();
private int PRIORITY = MAX_MOVIE_RECOMMENDATIONS + MAX_SHOW_RECOMMENDATIONS;
private int TOTAL_COUNT=0;
@Override
protected void onHandleIntent(Intent intent) {
if(!VersionUtils.isAndroidTV()) {
return;
}
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
MediaProvider.Filters movieFilter = new MediaProvider.Filters();
movieFilter.order = MediaProvider.Filters.Order.DESC;
movieFilter.sort = MediaProvider.Filters.Sort.POPULARITY;
MediaProvider.Filters showsFilter = new MediaProvider.Filters();
showsFilter.order = MediaProvider.Filters.Order.DESC;
showsFilter.sort = MediaProvider.Filters.Sort.DATE;
final AtomicBoolean mMoviesCallFinished = new AtomicBoolean(false);
final AtomicBoolean mShowsCallFinished = new AtomicBoolean(false);
Timber.d("Fetching movies");
//fetch movies
mMovieProvider.getList(movieFilter, new MediaProvider.Callback() {
@Override
public void onSuccess(MediaProvider.Filters filters, ArrayList<Media> items, boolean changed) {
Timber.d(String.format("loaded %s movies", items.size()));
mMovies.addAll(items);
mMoviesCallFinished.set(true);
}
@Override
public void onFailure(Exception e) {
Timber.d("Failed to fetch movies");
mMoviesCallFinished.set(true);
}
});
Timber.d("Fetching shows");
//fetch shows
mShowProvider.getList(showsFilter, new MediaProvider.Callback() {
@Override
public void onSuccess(MediaProvider.Filters filters, ArrayList<Media> items, boolean changed) {
Timber.d(String.format("loaded %s shows", items.size()));
mShows.addAll(items);
mShowsCallFinished.set(true);
}
@Override
public void onFailure(Exception e) {
Timber.d("Failed to fetch shows");
mShowsCallFinished.set(true);
}
});
//wait for callbacks to finish
while (!mShowsCallFinished.get() || !mMoviesCallFinished.get()) {
Timber.d("Waiting on callbacks");
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Timber.d("mShowsCallFinished: " + mShowsCallFinished.get());
Timber.d("mMoviesCallFinished: " + mMoviesCallFinished.get());
//process items
Timber.d("Updating recommendation cards");
if (mMovies.size() == 0 && mShows.size() == 0)
return;
RecommendationBuilder builder = new RecommendationBuilder()
.setContext(getApplicationContext())
.setSmallIcon(R.drawable.header_logo);
buildMovieRecommendations(builder);
buildShowRecommendations(builder);
}
private void buildMovieRecommendations(@NonNull RecommendationBuilder builder) {
Timber.d("building movie recommendations");
try {
int count = 0;
for (Media media : mMovies) {
Movie movie = (Movie) media;
Timber.d("Recommendation - " + movie.title);
PRIORITY--;
TOTAL_COUNT--;
builder.setBackgroundContentUri(RecommendationContentProvider.CONTENT_URI + URLEncoder.encode(movie.headerImage, "UTF-8"))
.setId(TOTAL_COUNT)
.setPriority(PRIORITY)
.setTitle(movie.title)
.setDescription(movie.synopsis)
.setImage(movie.image)
.setIntent(buildPendingIntent(movie))
.build();
if (++count >= MAX_MOVIE_RECOMMENDATIONS) {
break;
}
}
} catch (IOException e) {
Timber.e("Unable to update recommendation", e);
}
}
private void buildShowRecommendations(@NonNull RecommendationBuilder builder) {
Timber.d("building show recommendations");
try {
int count = 0;
for (Media media : mShows) {
Show show = (Show) media;
Timber.d("Recommendation - " + show.title);
Episode latestEpisode = findLatestEpisode(show);
PRIORITY--;
TOTAL_COUNT--;
builder.setBackgroundContentUri(RecommendationContentProvider.CONTENT_URI + URLEncoder.encode(show.headerImage, "UTF-8"))
.setId(TOTAL_COUNT)
.setPriority(PRIORITY)
.setTitle(show.title)
.setDescription(latestEpisode == null ? "" : getString(R.string.episode_number_format, latestEpisode.episode))
.setImage(show.image)
.setIntent(buildPendingIntent(show))
.build();
if (++count >= MAX_SHOW_RECOMMENDATIONS) {
break;
}
}
} catch (IOException e) {
Timber.e("Unable to update recommendation", e);
}
}
private Episode findLatestEpisode(Show show) {
if (show.episodes == null || show.episodes.size() == 0) return null;
return show.episodes.get(show.episodes.size());
}
private PendingIntent buildPendingIntent(Media media) {
Intent detailIntent = PTVMediaDetailActivity.buildIntent(this, media);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
stackBuilder.addParentStack(PTVMediaDetailActivity.class);
stackBuilder.addNextIntent(detailIntent);
// Ensure a unique PendingIntents, otherwise all recommendations end up with the same
// PendingIntent
detailIntent.setAction(media.videoId);
PendingIntent intent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
return intent;
}
}