/* * Copyright (C) 2013 Simon Vig Therkildsen * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package net.simonvt.cathode.scheduler; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import javax.inject.Inject; import net.simonvt.cathode.api.enumeration.ItemType; import net.simonvt.cathode.api.util.TimeUtils; import net.simonvt.cathode.jobqueue.Job; import net.simonvt.cathode.provider.DatabaseContract.MovieColumns; import net.simonvt.cathode.provider.MovieDatabaseHelper; import net.simonvt.cathode.provider.ProviderSchematic.Movies; import net.simonvt.cathode.remote.action.CancelCheckin; import net.simonvt.cathode.remote.action.movies.CalendarHideMovie; import net.simonvt.cathode.remote.action.movies.CheckInMovie; import net.simonvt.cathode.remote.action.movies.CollectMovie; import net.simonvt.cathode.remote.action.movies.DismissMovieRecommendation; import net.simonvt.cathode.remote.action.movies.RateMovie; import net.simonvt.cathode.remote.action.movies.WatchedMovie; import net.simonvt.cathode.remote.action.movies.WatchlistMovie; import net.simonvt.cathode.remote.sync.comments.SyncComments; import net.simonvt.cathode.remote.sync.movies.SyncMovie; import net.simonvt.cathode.remote.sync.movies.SyncMovieCredits; import net.simonvt.cathode.remote.sync.movies.SyncRelatedMovies; import net.simonvt.cathode.tmdb.api.movie.SyncMovieImages; import net.simonvt.cathode.util.DateUtils; import net.simonvt.schematic.Cursors; public class MovieTaskScheduler extends BaseTaskScheduler { @Inject MovieDatabaseHelper movieHelper; public MovieTaskScheduler(Context context) { super(context); } public void sync(final long movieId) { sync(movieId, null); } public void sync(final long movieId, final Job.OnDoneListener onDoneListener) { execute(new Runnable() { @Override public void run() { final long traktId = movieHelper.getTraktId(movieId); final int tmdbId = movieHelper.getTmdbId(movieId); queue(new SyncMovie(traktId)); queue(new SyncMovieImages(tmdbId)); queue(new SyncMovieCredits(traktId)); queue(new SyncRelatedMovies(traktId)); Job job = new SyncComments(ItemType.MOVIE, traktId); job.registerOnDoneListener(onDoneListener); queue(job); } }); } public void syncComments(final long movieId) { execute(new Runnable() { @Override public void run() { final long traktId = movieHelper.getTraktId(movieId); queue(new SyncComments(ItemType.MOVIE, traktId)); ContentValues values = new ContentValues(); values.put(MovieColumns.LAST_COMMENT_SYNC, System.currentTimeMillis()); context.getContentResolver().update(Movies.withId(movieId), values, null, null); } }); } public void syncRelated(final long movieId, final Job.OnDoneListener onDoneListener) { execute(new Runnable() { @Override public void run() { final long traktId = movieHelper.getTraktId(movieId); Job job = new SyncRelatedMovies(traktId); job.registerOnDoneListener(onDoneListener); queue(job); ContentValues values = new ContentValues(); values.put(MovieColumns.LAST_RELATED_SYNC, System.currentTimeMillis()); context.getContentResolver().update(Movies.withId(movieId), values, null, null); } }); } public void syncCredits(final long movieId, final Job.OnDoneListener onDoneListener) { execute(new Runnable() { @Override public void run() { final long traktId = movieHelper.getTraktId(movieId); Job job = new SyncMovieCredits(traktId); job.registerOnDoneListener(onDoneListener); queue(job); ContentValues values = new ContentValues(); values.put(MovieColumns.LAST_CREDITS_SYNC, System.currentTimeMillis()); context.getContentResolver().update(Movies.withId(movieId), values, null, null); } }); } /** * Add episodes watched outside of trakt to user library. * * @param movieId The database id of the episode. * @param watched Whether the episode has been watched. */ public void setWatched(final long movieId, final boolean watched) { execute(new Runnable() { @Override public void run() { String watchedAt = null; long watchedAtMillis = 0L; if (watched) { watchedAt = TimeUtils.getIsoTime(); watchedAtMillis = TimeUtils.getMillis(watchedAt); } final long traktId = movieHelper.getTraktId(movieId); movieHelper.setWatched(movieId, watched, watchedAtMillis); queue(new WatchedMovie(traktId, watched, watchedAt)); } }); } public void setIsInWatchlist(final long movieId, final boolean inWatchlist) { execute(new Runnable() { @Override public void run() { String listedAt = null; long listedAtMillis = 0L; if (inWatchlist) { listedAt = TimeUtils.getIsoTime(); listedAtMillis = TimeUtils.getMillis(listedAt); } final long traktId = movieHelper.getTraktId(movieId); movieHelper.setIsInWatchlist(movieId, inWatchlist, listedAtMillis); queue(new WatchlistMovie(traktId, inWatchlist, listedAt)); } }); } public void setIsInCollection(final long movieId, final boolean inCollection) { execute(new Runnable() { @Override public void run() { String collectedAt = null; long collectedAtMillis = 0L; if (inCollection) { collectedAt = TimeUtils.getIsoTime(); collectedAtMillis = TimeUtils.getMillis(collectedAt); } final long traktId = movieHelper.getTraktId(movieId); movieHelper.setIsInCollection(movieId, inCollection, collectedAtMillis); queue(new CollectMovie(traktId, inCollection, collectedAt)); } }); } /** * Check into a movie on trakt. Think of this method as in between a seen and a scrobble. * After checking in, the trakt will automatically display it as watching then switch over to * watched status once * the duration has elapsed. * * @param movieId The database id of the movie. */ public void checkin(final long movieId, final String message, final boolean facebook, final boolean twitter, final boolean tumblr) { execute(new Runnable() { @Override public void run() { Cursor c = context.getContentResolver().query(Movies.WATCHING, new String[] { MovieColumns.ID, MovieColumns.EXPIRES_AT, }, null, null, null); final long currentTime = System.currentTimeMillis(); long expires = 0; if (c.moveToFirst()) { expires = Cursors.getLong(c, MovieColumns.EXPIRES_AT); } if (c.getCount() == 0 || (expires >= currentTime && expires > 0)) { Cursor movie = context.getContentResolver().query(Movies.withId(movieId), new String[] { MovieColumns.ID, MovieColumns.RUNTIME, }, null, null, null); movie.moveToFirst(); final int runtime = Cursors.getInt(movie, MovieColumns.RUNTIME); movie.close(); final long startedAt = System.currentTimeMillis(); final long expiresAt = startedAt + runtime * DateUtils.MINUTE_IN_MILLIS; ContentValues cv = new ContentValues(); cv.put(MovieColumns.CHECKED_IN, true); cv.put(MovieColumns.STARTED_AT, startedAt); cv.put(MovieColumns.EXPIRES_AT, expiresAt); context.getContentResolver().update(Movies.withId(movieId), cv, null, null); final long traktId = movieHelper.getTraktId(movieId); queue(new CheckInMovie(traktId, message, facebook, twitter, tumblr)); } c.close(); } }); } /** * Notify trakt that user wants to cancel their current check in. */ public void cancelCheckin() { execute(new Runnable() { @Override public void run() { Cursor c = context.getContentResolver().query(Movies.WATCHING, new String[] { MovieColumns.TMDB_ID, }, null, null, null); if (c.moveToFirst()) { ContentValues cv = new ContentValues(); cv.put(MovieColumns.CHECKED_IN, false); context.getContentResolver().update(Movies.WATCHING, cv, null, null); queue(new CancelCheckin()); } c.close(); } }); } public void dismissRecommendation(final long movieId) { execute(new Runnable() { @Override public void run() { final long traktId = movieHelper.getTraktId(movieId); ContentValues cv = new ContentValues(); cv.put(MovieColumns.RECOMMENDATION_INDEX, -1); context.getContentResolver().update(Movies.withId(movieId), cv, null, null); queue(new DismissMovieRecommendation(traktId)); } }); } /** * Rate a movie on trakt. Depending on the user settings, this will also send out social updates * to facebook, * twitter, and tumblr. * * @param movieId The database id of the movie. * @param rating A rating betweeo 1 and 10. Use 0 to undo rating. */ public void rate(final long movieId, final int rating) { execute(new Runnable() { @Override public void run() { String ratedAt = TimeUtils.getIsoTime(); long ratedAtMillis = TimeUtils.getMillis(ratedAt); final long traktId = movieHelper.getTraktId(movieId); ContentValues cv = new ContentValues(); cv.put(MovieColumns.USER_RATING, rating); cv.put(MovieColumns.RATED_AT, ratedAtMillis); context.getContentResolver().update(Movies.withId(movieId), cv, null, null); queue(new RateMovie(traktId, rating, ratedAt)); } }); } public void hideFromCalendar(final long movieId, final boolean hidden) { execute(new Runnable() { @Override public void run() { final long traktId = movieHelper.getTraktId(movieId); queue(new CalendarHideMovie(traktId, hidden)); ContentValues values = new ContentValues(); values.put(MovieColumns.HIDDEN_CALENDAR, hidden); context.getContentResolver().update(Movies.withId(movieId), values, null, null); } }); } }